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.

2441 lines
87 KiB

  1. PAGE ,132
  2. TITLE GALLOC - Global memory allocator
  3. .sall
  4. .xlist
  5. include kernel.inc
  6. include protect.inc
  7. .list
  8. .286p
  9. DataBegin
  10. externB Kernel_flags
  11. externB fCheckFree
  12. externW pGlobalHeap
  13. externW WinFlags
  14. gsearch_state_machine dw 0
  15. GA_ALIGN_BYTES = (((GA_ALIGN+1) SHL 4) - 1)
  16. GA_MASK_BYTES = NOT GA_ALIGN_BYTES
  17. ifdef WOW
  18. externB fInAlloc
  19. externW SelectorFreeBlock
  20. endif
  21. public DpmiMemory, DpmiBlockCount
  22. DpmiMemory DpmiBlock NUM_DPMI_BLOCKS dup (<>)
  23. DpmiBlockCount dw 0
  24. DataEnd
  25. sBegin CODE
  26. assumes CS,CODE
  27. externNP gcompact
  28. externNP gmovebusy
  29. externNP gmoveable
  30. externNP gslidecommon
  31. externNP galign
  32. externNP get_physical_address
  33. externNP set_physical_address
  34. externNP alloc_data_sel
  35. externNP set_sel_limit
  36. externNP free_sel
  37. externNP get_blotto
  38. externNP cmp_sel_address
  39. externNP alloc_data_sel_above
  40. externNP PreallocSel
  41. externNP DPMIProc
  42. ifdef WOW
  43. externNP alloc_special_sel
  44. endif
  45. ;-----------------------------------------------------------------------;
  46. ; gsearch ;
  47. ; ;
  48. ; Searches from start to finish for a free global object to allocate ;
  49. ; space from. For a fixed request it tries to get the space as low as ;
  50. ; possible, moving movable out of the way if neccessary. For movable ;
  51. ; requests it also starts at the bottom. For discardable code it ;
  52. ; starts from the top, only using the first free block it finds. ;
  53. ; If at first blush it can't find a block it compacts memory and tries ;
  54. ; again. ;
  55. ; When it finally finds a block it gsplices it in, makes sure the ;
  56. ; arena headers are fine, and returns the allocated block. ;
  57. ; Called from within the global memory manager's critical section. ;
  58. ; ;
  59. ; Arguments: ;
  60. ; AX = allocations flags ;
  61. ; BX = #paras ;
  62. ; CX = owner field value ;
  63. ; DS:DI = address of global arena information structure ;
  64. ; ;
  65. ; Returns: ;
  66. ; AX = data address of block allocated or NULL ;
  67. ; BX = ga_prev or ga_next ;
  68. ; DX = allocation flags ;
  69. ; ;
  70. ; Error Returns: ;
  71. ; ZF = 1 ;
  72. ; AX = 0 ;
  73. ; BX = ga_prev or ga_next ;
  74. ; DX = size of largest free block ;
  75. ; ;
  76. ; Registers Preserved: ;
  77. ; DI,DS ;
  78. ; ;
  79. ; Registers Destroyed: ;
  80. ; CX,SI,ES ;
  81. ; ;
  82. ; Calls: ;
  83. ; galign ;
  84. ; gfindfree ;
  85. ; fmovebusy ;
  86. ; gcheckfree ;
  87. ; gcompact ;
  88. ; gsplice ;
  89. ; gzero ;
  90. ; gmarkfree ;
  91. ; use_EMS_land ;
  92. ; use_lower_land ;
  93. ; ;
  94. ; History: ;
  95. ; ;
  96. ; Wed Jul 22, 1987 11:15:19p -by- David N. Weise [davidw] ;
  97. ; Fixed BOGUS BLOCK freeing yet again. ;
  98. ; ;
  99. ; Sun May 10, 1987 11:29:38p -by- David N. Weise [davidw] ;
  100. ; Added the state machine to handle the case of wanting to search ;
  101. ; both global arenas. ;
  102. ; ;
  103. ; Sat Feb 28, 1987 06:31:11p -by- David N. Weise [davidw] ;
  104. ; Putting in support for allocating discardable code from EEMS land. ;
  105. ; ;
  106. ; Tue Dec 30, 1986 01:54:50p -by- David N. Weise [davidw] ;
  107. ; Made sure it freed any bogus blocks created. ;
  108. ; ;
  109. ; Thu Nov 20, 1986 04:00:06p -by- David N. Weise [davidw] ;
  110. ; Rewrote it use the global free list. Also made it put fixed requests ;
  111. ; as low as possible and to search again after a compact. ;
  112. ; ;
  113. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  114. ; Added support for the free list of global partitions. ;
  115. ; ;
  116. ; Tue Sep 23, 1986 04:35:39p -by- David N. Weise [davidw] ;
  117. ; Added this nifty comment block. ;
  118. ;-----------------------------------------------------------------------;
  119. assumes ds,nothing
  120. assumes es,nothing
  121. cProc gsearch,<PUBLIC,NEAR>
  122. cBegin nogen
  123. SetKernelDS
  124. mov gsearch_state_machine,codeOFFSET grow_heap
  125. mov ds,pGlobalHeap
  126. UnSetKernelDS
  127. look_again:
  128. push bx ; Save requested size
  129. push cx ; Save owner
  130. push ax ; Save flags
  131. add bx,1 ; Room for header (set flags for galign)
  132. call galign ; Get requested size in DX
  133. push dx ; Save adjusted requested size
  134. inc dx ; Fail quickly if asking for
  135. jnz @f ; too much memory
  136. jmp gsearch_fail
  137. @@:
  138. dec dx
  139. ; see if there is any one free space large enough for the request first
  140. mov si,dx
  141. dec si ; Room for header
  142. mov cx,[di].gi_free_count
  143. jcxz were_hosed_from_start
  144. mov es,[di].hi_first
  145. is_there_one:
  146. mov es,es:[di].ga_freenext
  147. cmp si,es:[di].ga_size
  148. jbe short got_one
  149. loop is_there_one
  150. were_hosed_from_start:
  151. jmp space_not_found
  152. got_one:
  153. mov bx,ga_prev ; search backwards
  154. test al,GA_ALLOCHIGH
  155. jz short alloc_low
  156. ;------ allocate disc code -------
  157. public alloc_high
  158. alloc_high:
  159. mov cx,[di].gi_free_count
  160. mov es,[di].hi_last ; Start with last entry.
  161. alloc_high_loop:
  162. mov es,es:[di].ga_freeprev
  163. cmp si,es:[di].ga_size
  164. ja short loop_it
  165. jmp afound ; Yes, exit search loop
  166. loop_it:
  167. loop alloc_high_loop
  168. were_hosed:
  169. jmps space_not_found
  170. ;------ allocate moveable ---------
  171. public alloc_low
  172. alloc_low:
  173. mov bl,ga_next ; Search forwards.
  174. test al,GA_MOVEABLE
  175. jz short alloc_fixed
  176. call gcheckfree ; Room for requested size?
  177. jb short were_hosed
  178. jmp afound
  179. ;------ allocate fixed ------------
  180. public alloc_fixed
  181. alloc_fixed:
  182. mov es,[di].hi_first ; Start with first entry.
  183. mov cx,[di].hi_count
  184. mov es,es:[bx] ; Skip first sentinel
  185. alloc_fixed_loop:
  186. push cx
  187. push es
  188. call is_there_theoretically_enough_space
  189. cmp ax,dx
  190. jb short nope
  191. pop es
  192. pop cx
  193. call can_we_clear_this_space
  194. jz short anext1
  195. call gcheckfree ; Yes, room for requested size?
  196. jb short anext1
  197. ; Now we have enough free space,
  198. ; slide it back as far as possible.
  199. push ax ; This is to prevent us blocking
  200. push dx ; the growth of moveable blocks.
  201. keep_sliding:
  202. push es
  203. mov es,es:[di].ga_prev
  204. mov ax,es
  205. mov dx,es:[di].ga_size
  206. call gmoveable ; Is previous block moveable?
  207. pop es
  208. jz short no_slide
  209. call PreallocSel
  210. jz no_slide
  211. push bx
  212. mov bx, ga_prev ; Sliding backwards
  213. push es ; gslide will invalidate this block
  214. call gslidecommon ; C - calling convention
  215. call free_sel ; free the pushed selector
  216. pop bx
  217. jmps keep_sliding
  218. no_slide:
  219. pop dx ; requested size
  220. pop ax ; block size
  221. pop si ; adjusted requested size
  222. pop cx ; flags
  223. push cx ; these two expected on stack later
  224. push si
  225. test ch,GA_ALLOC_DOS ;If this is a DOS land alloc
  226. jz okey_dokey ; make sure that the block
  227. push ax ; we found is below the 1 meg
  228. push dx ; boundry, or fail the request
  229. cCall get_physical_address,<es>
  230. cmp dx,0010h ; (0010:0000 = 1024k = 1 meg)
  231. pop dx
  232. pop ax
  233. jae space_not_found
  234. okey_dokey:
  235. jmp afound
  236. nope: or ax,ax
  237. jz short hosed_again
  238. anext: pop si ; get rid of CX, ES on the stack
  239. pop si
  240. anext1: mov es,es:[bx]
  241. loop alloc_fixed_loop
  242. jmps and_again
  243. hosed_again:
  244. pop es
  245. pop cx
  246. and_again:
  247. ; no one space big enough, try compacting
  248. public space_not_found
  249. space_not_found:
  250. pop dx ; get size
  251. pop ax ; get flags
  252. push ax
  253. push dx
  254. test al,GA_ALLOCHIGH
  255. jnz short ask_for_what_we_need
  256. add dx,0400h ; ask for 16k more
  257. jnc short ask_for_what_we_need ; no overflow
  258. mov dx,-1
  259. ask_for_what_we_need:
  260. SetKernelDS
  261. push gsearch_state_machine
  262. mov ds,pGlobalHeap
  263. UnSetKernelDS
  264. retn
  265. ;------------------------------
  266. public do_compact ; for debugging
  267. do_compact:
  268. call gcompact
  269. SetKernelDS
  270. mov gsearch_state_machine,codeOFFSET gsearch_fail
  271. mov ds,pGlobalHeap
  272. UnSetKernelDS
  273. over_compact:
  274. pop dx
  275. pop ax
  276. pop cx
  277. pop bx
  278. jmp look_again
  279. ;------------------------------
  280. public grow_heap ; for debugging
  281. grow_heap:
  282. SetKernelDS
  283. mov gsearch_state_machine,codeOFFSET do_compact
  284. mov ds,pGlobalHeap
  285. UnSetKernelDS
  286. call GrowHeap
  287. jmp over_compact
  288. ;------------------------------
  289. public gsearch_fail ; for debugging
  290. gsearch_fail: ; get size of largest free block
  291. xor dx,dx
  292. mov cx,[di].gi_free_count
  293. jcxz gs_failure
  294. mov es,[di].hi_first
  295. largest_loop:
  296. mov es,es:[di].ga_freenext
  297. mov ax,es:[di].ga_size
  298. cmp dx,ax
  299. jae short new_smaller
  300. mov dx,ax
  301. new_smaller:
  302. loop largest_loop
  303. gs_failure:
  304. pop ax ; adjusted requested size
  305. pop ax ; AX = flags
  306. pop cx ; CX = owner field
  307. pop ax ; waste requested size
  308. xor ax,ax ; Return zero, with ZF = 1
  309. ret
  310. ; Here when we have a block big enough.
  311. ; ES:DI = address of block
  312. ; AX = size of block, including header
  313. ; DX = requested size, including header
  314. ; BX = ga_prev if backwards search and ga_next if forwards search
  315. afound:
  316. ifdef WOW ; Optimized path for WOW
  317. push ds
  318. SetkernelDS
  319. cmp fInAlloc, 1
  320. UnSetKernelDS
  321. pop ds
  322. jne nothing_special
  323. aallocsels:
  324. pop cx ; adjusted requested size
  325. pop ax ; get the flags
  326. push ax ; restore the stack
  327. push cx
  328. push ax ; allocation flags
  329. push es ; Selector FreeBlock
  330. mov ax, es:[di].ga_size
  331. push ax ; actual size of freeblock
  332. inc ax
  333. mov cx, ax ; save in cx too
  334. sub cx, dx
  335. push cx ; size new freeblock
  336. push dx ; adjusted size
  337. push bx ; bl = ga_prev pr ga_next
  338. call alloc_special_sel
  339. jz gs_failure ; no selector
  340. jmps no_sel_wanted
  341. nothing_special:
  342. endif ; End Optimized path for WOW
  343. mov ax,es:[di].ga_size ; Use actual size of free block
  344. inc ax
  345. mov cx,ax ; See how much extra space there is
  346. sub cx,dx ; (found size - requested size)
  347. jcxz no_sel_wanted
  348. call PreallocSel ; Make sure we can splice
  349. jz gs_failure ; no selector
  350. no_sel_wanted:
  351. mov ax,es:[di].ga_freeprev
  352. xor si,si ; Assume nothing extra to free
  353. call gdel_free ; remove the alloc block from freelist
  354. if KDEBUG
  355. push ds
  356. SetKernelDS
  357. cmp fCheckFree,0
  358. pop ds
  359. UnSetKernelDS
  360. jnz short not_during_boot
  361. call check_this_space
  362. not_during_boot:
  363. endif
  364. jcxz aexit ; No, continue
  365. cmp bl,ga_prev ; Yes, scanning forwards or backwards?
  366. je short abackward ; Backwards.
  367. ; mov si,es ; Forwards. Put extra space at end of
  368. mov si,dx ; free block
  369. call gsplice ; ES:DI = block we are allocating
  370. jmps aexit ; SI = block to mark as free
  371. abackward:
  372. mov si,es:[di].ga_size ; Scanning backwards. Put extra space
  373. sub si,dx ; at beginning of free block.
  374. inc si
  375. call gsplice
  376. mov es,si ; ES:DI = block we are allocating
  377. mov si,es:[di].ga_prev ; SI = block to mark as free
  378. ; Here with allocated block
  379. ; AX = data address or zero if nothing allocated
  380. ; ES:DI = address of block to mark as busy and zero init if requested
  381. ; SI = address of block to mark as free
  382. aexit:
  383. pop dx ; waste adjusted requested size
  384. pop dx ; Restore flags
  385. pop es:[di].ga_owner ; Mark block as busy with owner field value
  386. pop cx ; waste requested size
  387. mov es:[di].ga_lruprev,di
  388. mov es:[di].ga_lrunext,di
  389. push ax ; previous free block
  390. mov al,GA_SEGTYPE
  391. and al,dl
  392. test dh,GAH_NOTIFY
  393. jz short no_notify
  394. or al,GAH_NOTIFY
  395. no_notify:
  396. mov es:[di].ga_flags,al ; Store segment type bits
  397. mov ax,es ; AX = address of client data
  398. test dl,GA_ZEROINIT ; Want it zeroed?
  399. jz short aexit1 ; No, all done
  400. push ax
  401. cCall get_blotto
  402. mov cx,es:[di].ga_size ; Yes, zero paragraphs
  403. ; dec cx ; to end of this block
  404. push bx
  405. mov bx,ax ; from beginning of client data
  406. call gzero ; zero them
  407. pop bx
  408. pop ax
  409. aexit1:
  410. mov es,si ; Free any extra space
  411. pop si ; previous free block
  412. dec si ; make it RING 0 for gmarkfree
  413. call gmarkfree
  414. or ax,ax
  415. ret ; Return AX points to client portion
  416. ; of block allocated.
  417. cEnd nogen
  418. ;-----------------------------------------------------------------------;
  419. ; is_there_theoretically_enough_space
  420. ;
  421. ; Starting at the given arena checks to see if there are enough
  422. ; continuous free and unlocked moveable blocks.
  423. ;
  424. ; Entry:
  425. ; CX = arenas to search
  426. ; DX = size requested
  427. ; DS = BurgerMaster
  428. ; ES:DI = arena to start from
  429. ;
  430. ; Returns:
  431. ; AX = 0 => not enough space and no more memory left to search
  432. ; AX = 1 => not enough space in this block, but maybe....
  433. ; otherwise
  434. ; AX = size of block
  435. ;
  436. ; Registers Destroyed:
  437. ; CX,SI
  438. ;
  439. ; Registers Preserved:
  440. ; BX,DX,DI,ES
  441. ;
  442. ; History:
  443. ; Mon 05-Sep-1988 15:21:14 -by- David N. Weise [davidw]
  444. ; Moved it here from gsearch so that grealloc could use it as well.
  445. ;-----------------------------------------------------------------------;
  446. assumes ds,nothing
  447. assumes es,nothing
  448. cProc is_there_theoretically_enough_space,<PUBLIC,NEAR>
  449. cBegin nogen
  450. xor ax,ax
  451. ittes:
  452. cmp es:[di].ga_owner,di
  453. jne short is_it_moveable
  454. add ax,es:[di].ga_size
  455. push bx
  456. push cx
  457. push ax
  458. push dx
  459. mov cx,word ptr [di].gi_disfence_hi ; See if begin of reserve area
  460. mov bx,word ptr [di].gi_disfence_lo ; is above end of free block
  461. cCall get_physical_address,<es:[di].ga_next>
  462. sub bx,ax
  463. sbb cx,dx ; used as cmp ONLY CARRY is VALID
  464. pop dx
  465. pop ax
  466. jb short ittes_above_fence ; All below fence?
  467. pop cx
  468. pop bx
  469. jmps this_ones_free
  470. ittes_above_fence:
  471. REPT 4
  472. shr cx,1
  473. rcr bx,1
  474. ENDM
  475. add ax,bx ; No, Reduce apparent size of free block
  476. pop cx
  477. pop bx
  478. inc ax
  479. cmp ax,dx
  480. jae short theoretically_enough
  481. jmps absolutely_not
  482. is_it_moveable:
  483. test es:[di].ga_flags,GA_DISCCODE
  484. jnz short absolutely_not
  485. test es:[di].ga_handle,GA_FIXED ; See if movable.
  486. jnz short theoretically_not
  487. cmp es:[di].ga_count,0
  488. jne short theoretically_not ; See if locked.
  489. add ax,es:[di].ga_size
  490. this_ones_free:
  491. inc ax
  492. cmp ax,dx
  493. jae short theoretically_enough
  494. mov es,es:[ga_next]
  495. loop ittes
  496. ; For the case of gsearch we should never get here for two reasons.
  497. ; 1) It should be impossible to have no discardable code loaded, in
  498. ; this case we would have failed in the above loop. 2) We checked
  499. ; at the very start for a free block somewhere that could have
  500. ; satisfied the request. In our mucking around to load as low as
  501. ; possible we destroyed this free block and we did not produce a free
  502. ; block we could use. However we know from debugging code in 2.03
  503. ; that this happens extremely rarely. Because of the rareness of
  504. ; this event we will not try to recover, instead we simply fail the call.
  505. absolutely_not:
  506. mov ax,-1 ; return AX = 0
  507. theoretically_not:
  508. inc ax ; DX is even, => cmp the same.
  509. theoretically_enough:
  510. ret
  511. cEnd nogen
  512. ;-----------------------------------------------------------------------;
  513. ; can_we_clear_this_space
  514. ;
  515. ; Attempts to make a free space starting at the address moved in.
  516. ; To do this it moves moveable out of the area. The only subtlety
  517. ; involves a free block that stradles the end of wanted area. This
  518. ; may get broken into two pieces, the lower piece gets temporary marked
  519. ; as allocated and BOGUS, the upper piece will remain free.
  520. ;
  521. ; Entry:
  522. ; CX = max number of blocks to look at
  523. ; DX = size wanted in paragraphs
  524. ; DS = BurgerMaster
  525. ; ES:DI = beginning arena
  526. ;
  527. ; Returns:
  528. ; ZF = 0
  529. ; ES:DI points to free space
  530. ; ZF = 1
  531. ; couldn't free the space up
  532. ;
  533. ; Registers Destroyed:
  534. ; AX,SI
  535. ;
  536. ; History:
  537. ; Mon 05-Sep-1988 16:48:31 -by- David N. Weise [davidw]
  538. ; Moved it out of gsearch so that grealloc could use it.
  539. ;-----------------------------------------------------------------------;
  540. assumes ds,nothing
  541. assumes es,nothing
  542. cProc can_we_clear_this_space,<PUBLIC,NEAR>
  543. cBegin nogen
  544. push cx
  545. push es
  546. mov ax, es ; Beginning of space we want.
  547. cmp di,es:[di].ga_owner ; Is it free?
  548. jnz short can_we_move_it
  549. mov cx,dx
  550. dec cx
  551. cmp cx,es:[di].ga_size
  552. ja short asdf
  553. or ax,ax ; return ZF = 0
  554. pop es
  555. pop cx
  556. ret
  557. asdf: mov es,es:[di].ga_next
  558. public can_we_move_it
  559. can_we_move_it:
  560. push bx
  561. push cx
  562. push dx
  563. push es
  564. cmp es:[di].ga_owner,GA_BOGUS_BLOCK
  565. jnz short not_bogus
  566. xor si,si
  567. call gmarkfree
  568. jmp restart
  569. not_bogus:
  570. push ax
  571. cCall alloc_data_sel_above,<ax,dx>
  572. mov si, ax ; End of space we want.
  573. pop ax
  574. or si, si
  575. jnz got_marker_sel
  576. pop cx ; Trash es saved on stack
  577. jmp no_clear
  578. got_marker_sel:
  579. mov cx,[di].gi_free_count
  580. jcxz forget_it ; Nothing is free, so don't bother
  581. mov dx,es:[di].ga_size ; Yes, try to find a place for the
  582. mov es,[di].hi_first ; moveable block
  583. look_loop:
  584. mov es,es:[di].ga_freenext
  585. mov bx,es
  586. cCall cmp_sel_address,<bx,ax> ; It defeats our purpose to move the
  587. jb short check_this_out ; block to a free space we want.
  588. cCall cmp_sel_address,<bx,si>
  589. jb short is_there_hope
  590. check_this_out:
  591. push ax
  592. call gcheckfree
  593. push cx
  594. jb short inopportune_free_space
  595. cCall free_sel,<si>
  596. pop cx
  597. pop ax
  598. pop si ; SI = moveable block for gmovebusy
  599. mov bx,ga_next
  600. call gmovebusy ; Move moveable block out of the way
  601. pop dx
  602. pop cx
  603. pop bx
  604. pop cx ; WAS pop es but es destroyed below
  605. pop cx
  606. mov es,si ; Replace the ES on the stack,
  607. ; the free block may have grown
  608. ; downward with the gmovebusy.
  609. jmp can_we_clear_this_space
  610. inopportune_free_space:
  611. pop cx
  612. pop ax
  613. loop look_loop
  614. forget_it:
  615. jmp couldnt_clear_it
  616. public is_there_hope
  617. is_there_hope:
  618. push ax
  619. push cx
  620. push dx
  621. cCall get_physical_address,<es:[di].ga_next>
  622. mov cx, dx
  623. mov bx, ax
  624. cmp cx, [di].gi_disfence_hi
  625. jb below_reserved
  626. ja above_reserved
  627. cmp bx, [di].gi_disfence_lo
  628. jbe short below_reserved
  629. above_reserved:
  630. mov cx, [di].gi_disfence_hi
  631. mov bx, [di].gi_disfence_lo
  632. below_reserved:
  633. cCall get_physical_address,<si>
  634. sub bx, ax
  635. sbb cx, dx ; Check the overlap.
  636. jae short overlap
  637. pop dx
  638. jmps inopportune_free_space
  639. overlap:
  640. REPT 4
  641. shr cx, 1
  642. rcr bx, 1
  643. ENDM
  644. mov cx, dx
  645. pop dx
  646. cmp bx,dx
  647. jbe short inopportune_free_space
  648. mov bx, ax
  649. cCall get_physical_address,<es>
  650. sub bx, ax
  651. sbb cx, dx
  652. REPT 4
  653. shr cx, 1
  654. rcr bx, 1
  655. ENDM
  656. cCall free_sel,<si>
  657. mov si, bx
  658. pop cx
  659. pop ax
  660. ; cut off the first piece for the original alloc
  661. push es:[di].ga_freeprev
  662. call gdel_free
  663. if KDEBUG
  664. push ds
  665. SetKernelDS
  666. cmp fCheckFree,0
  667. pop ds
  668. UnSetKernelDS
  669. jnz short not_during_boot_1
  670. call check_this_space
  671. not_during_boot_1:
  672. endif
  673. call gsplice
  674. ; ES:DI = addr of block to mark as busy, SI = addr of block to mark as free
  675. mov es:[di].ga_owner,GA_BOGUS_BLOCK
  676. mov es:[di].ga_lruprev,di
  677. mov es:[di].ga_lrunext,di
  678. mov es,si ; Free any extra space
  679. pop si ; previous free block
  680. dec si ; make it RING 0 for gmarkfree
  681. call gmarkfree
  682. restart:
  683. pop dx ; WAS pop es
  684. pop dx
  685. pop cx
  686. pop bx
  687. pop es
  688. pop cx
  689. jmp can_we_clear_this_space
  690. ; If here then failure! see if we made a bogus block!
  691. couldnt_clear_it:
  692. pop es ; recover block we wanted moved
  693. check_again:
  694. mov dx,es:[di].ga_next
  695. cCall cmp_sel_address,<dx,si> ; SI points to where bogus block
  696. ja short no_bogus_block ; would be.
  697. je short is_it_bogus
  698. mov es,dx
  699. cmp dx, es:[di].ga_next
  700. je short no_bogus_block
  701. jmp check_again
  702. is_it_bogus:
  703. cmp es:[di].ga_owner,GA_BOGUS_BLOCK
  704. jnz short no_bogus_block
  705. push si
  706. xor si,si
  707. call gmarkfree
  708. pop si
  709. no_bogus_block:
  710. if KDEBUG
  711. mov cx,[di].hi_count
  712. mov es,[di].hi_first
  713. bogus_all:
  714. cmp es:[di].ga_owner,GA_BOGUS_BLOCK
  715. jnz short not_me
  716. INT3_ANCIENT
  717. not_me: mov es,es:[di].ga_next
  718. loop bogus_all
  719. endif
  720. cCall free_sel,<si>
  721. no_clear:
  722. pop dx
  723. pop cx
  724. pop bx
  725. pop es
  726. pop cx
  727. xor ax,ax ; return ZF = 1
  728. ret
  729. cEnd nogen
  730. ;-----------------------------------------------------------------------;
  731. ; gfindfree ;
  732. ; ;
  733. ; Searches for a free block that is big enough but does not encroach ;
  734. ; on the area reserved for code swapping. ;
  735. ; ;
  736. ; Arguments: ;
  737. ; ES:DI = address of existing block to start looking at ;
  738. ; CX = #arena entries left to look at ;
  739. ; BX = direction of search, ga_next or ga_prev ;
  740. ; DX = #paragraphs needed ;
  741. ; DS:DI = address of global arena information structure ;
  742. ; ;
  743. ; Returns: ;
  744. ; AX = address of free block that is big enough ;
  745. ; ;
  746. ; Error Returns: ;
  747. ; AX = 0 ;
  748. ; ;
  749. ; Registers Preserved: ;
  750. ; BX,CX,DX,DI,SI,DS,ES ;
  751. ; ;
  752. ; Registers Destroyed: ;
  753. ; SI ;
  754. ; ;
  755. ; Calls: ;
  756. ; gcheckfree ;
  757. ; ;
  758. ; History: ;
  759. ; ;
  760. ; Wed Sep 24, 1986 10:16:38p -by- David N. Weise [davidw] ;
  761. ; Added this nifty comment block. ;
  762. ;-----------------------------------------------------------------------;
  763. cProc gfindfree,<PUBLIC,NEAR>
  764. cBegin nogen
  765. push cx
  766. push es
  767. gffloop:
  768. cmp es:[di].ga_owner,di ; Free block?
  769. jne short gffnext ; No, continue
  770. call gcheckfree ; Yes, is it big enough?
  771. mov ax,es
  772. jae short gffexit ; Yes, return
  773. gffnext:
  774. mov es,es:[bx] ; next or previous block
  775. loop gffloop
  776. gfffail:
  777. xor ax,ax ; No, return zero in AX
  778. gffexit:
  779. pop es
  780. pop cx
  781. ret
  782. cEnd nogen
  783. ;-----------------------------------------------------------------------;
  784. ; gcheckfree ;
  785. ; ;
  786. ; Checks the size of the passed free block against the passed desired ;
  787. ; size, making sure that the limitations of the code reserve area are ;
  788. ; not violated for objects other than discardable code. It also checks ;
  789. ; for Phantoms. ;
  790. ; ;
  791. ; Arguments: ;
  792. ; ES:DI = address of free block ;
  793. ; DX = #paragraphs needed ;
  794. ; DS:DI = address of global arena information structure ;
  795. ; ;
  796. ; Returns: ;
  797. ; CF = 0 block big enough ;
  798. ; AX = apparent size of free block ;
  799. ; ;
  800. ; Error Returns: ;
  801. ; none ;
  802. ; ;
  803. ; Registers Preserved: ;
  804. ; All ;
  805. ; ;
  806. ; Registers Destroyed: ;
  807. ; ;
  808. ; Calls: ;
  809. ; nothing ;
  810. ; ;
  811. ; History: ;
  812. ; ;
  813. ; Thu 27-Apr-1989 10:38:05 -by- David N. Weise [davidw] ;
  814. ; Fixed this to work in pmode. ;
  815. ; ;
  816. ; Thu Apr 02, 1987 10:45:22p -by- David N. Weise [davidw] ;
  817. ; Added Phantom support. ;
  818. ; ;
  819. ; Tue Sep 23, 1986 05:54:51p -by- David N. Weise [davidw] ;
  820. ; Added this nifty comment block. ;
  821. ;-----------------------------------------------------------------------;
  822. cProc gcheckfree,<PUBLIC,NEAR>
  823. cBegin nogen
  824. push si
  825. mov ax,es:[di].ga_size ; Compute size of free block
  826. inc ax
  827. test byte ptr [di].gi_cmpflags,GA_DISCCODE
  828. jnz short gcftest ; Discardable code not restricted
  829. ; Due to recent changes in the way disccode is allocated, we must make
  830. ; sure that non-disccode in never allocated above a disccode block.
  831. push es
  832. might_be_code_below:
  833. mov es,es:[di].ga_prev
  834. cmp es:[di].ga_owner,GA_NOT_THERE
  835. jz short might_be_code_below
  836. cmp es:[di].ga_owner,di ; Free block?
  837. jz short might_be_code_below
  838. test es:[di].ga_flags,GA_DISCCODE
  839. pop es
  840. jnz short gcfrsrv1
  841. push bx
  842. push cx
  843. push ax
  844. push dx
  845. mov cx,word ptr [di].gi_disfence_hi ; See if begin of reserve area
  846. mov bx,word ptr [di].gi_disfence_lo ; is above end of free block
  847. cCall get_physical_address,<es:[di].ga_next>
  848. sub bx,ax
  849. sbb cx,dx ; used as cmp ONLY CARRYY is VALID
  850. pop dx
  851. pop ax
  852. jae short gcftest1 ; Yes, return actual size of free block
  853. REPT 4
  854. shr cx,1
  855. rcr bx,1
  856. ENDM
  857. neg bx
  858. sub ax,bx ; No, Reduce apparent size of free block
  859. ja short gcftest1 ; Is it more than what is free?
  860. xor ax,ax ; Yes, then apparent size is zero
  861. ; Nothing left, set apparent size to 0
  862. gcftest1:
  863. pop cx
  864. pop bx
  865. jmps gcftest
  866. gcfrsrv1: ; Yes, then apparent size is zero
  867. xor ax,ax ; Nothing left, set apparent size to 0
  868. gcftest:
  869. cmp ax,dx ; Return results of the comparison
  870. pop si
  871. ret
  872. cEnd nogen
  873. ;-----------------------------------------------------------------------;
  874. ; gsplice ;
  875. ; ;
  876. ; Splits one block into two. ;
  877. ; ;
  878. ; Arguments: ;
  879. ; SI = size in paragraphs of new block to make ;
  880. ; ES:DI = address of existing block ;
  881. ; DS:DI = address of global arena information structure ;
  882. ; ;
  883. ; Returns: ;
  884. ; SI = address of new block ;
  885. ; ;
  886. ; Error Returns: ;
  887. ; nothing ;
  888. ; ;
  889. ; Registers Preserved: ;
  890. ; AX,BX,DX,DI,DS,ES ;
  891. ; ;
  892. ; Registers Destroyed: ;
  893. ; CX ;
  894. ; ;
  895. ; Calls: ;
  896. ; nothing ;
  897. ; History: ;
  898. ; ;
  899. ; Tue Sep 23, 1986 03:50:30p -by- David N. Weise [davidw] ;
  900. ; Added this nifty comment block. ;
  901. ;-----------------------------------------------------------------------;
  902. cProc gsplice,<PUBLIC,NEAR>
  903. cBegin nogen
  904. push bx
  905. push dx
  906. mov dx,si ; save size
  907. mov bx,es:[di].ga_size
  908. sub bx,dx ; get size of 2nd new block made
  909. push ax
  910. push bx
  911. push dx
  912. ifdef WOW ; Optimized path for WOW
  913. push ds
  914. SetkernelDS
  915. mov ax, SelectorFreeBlock ; same as fInAlloc == 1
  916. or ax, ax
  917. UnSetKernelDS
  918. pop ds
  919. jnz gsplice_oldpath2
  920. gsplice_oldpath:
  921. endif ; end optimized path for WOW
  922. mov bx,si
  923. xor cx,cx
  924. REPT 4
  925. shl bx,1
  926. rcl cx,1
  927. ENDM
  928. cCall get_physical_address,<es>
  929. add ax,bx
  930. adc dx,cx
  931. cCall alloc_data_sel,<dx,ax,1>
  932. ifdef WOW
  933. gsplice_oldpath2:
  934. endif
  935. mov si,ax
  936. pop dx
  937. pop bx
  938. pop ax
  939. inc [di].hi_count ; Adding new arena entry
  940. push si ; save new
  941. push es ; save old
  942. mov cx,si ; save old.next
  943. xchg es:[di].ga_next,cx ; and old.next = new
  944. mov es,cx
  945. mov es:[di].ga_prev,si ; [old old.next].prev = new
  946. mov es,si
  947. mov es:[di].ga_next,cx ; new.next = old old.next
  948. mov es:[di].ga_size,bx
  949. pop cx ; new.prev = old
  950. mov es:[di].ga_sig,GA_SIGNATURE
  951. mov es:[di].ga_owner,di ; Zero owner & handle fields
  952. mov es:[di].ga_flags,0 ; For good measure.
  953. mov es:[di].ga_prev,cx
  954. mov es:[di].ga_handle,di
  955. mov es,cx ; ES = old
  956. dec dx ; get size of 1st block made
  957. mov es:[di].ga_size,dx
  958. pop si ; restore new
  959. pop dx
  960. pop bx
  961. ret
  962. cEnd nogen
  963. ;-----------------------------------------------------------------------;
  964. ; gjoin ;
  965. ; ;
  966. ; Merges a block into his previous neighbor. ;
  967. ; ;
  968. ; Arguments: ;
  969. ; ES:DI = address of block to remove ;
  970. ; DS:DI = address of global arena information structure ;
  971. ; ;
  972. ; Returns: ;
  973. ; nothing ;
  974. ; ;
  975. ; Error Returns: ;
  976. ; nothing ;
  977. ; ;
  978. ; Registers Preserved: ;
  979. ; AX,BX,CX,DX,DI,SI,DS,ES ;
  980. ; ;
  981. ; Registers Destroyed: ;
  982. ; SI ;
  983. ; ;
  984. ; Calls: ;
  985. ; gdel_free ;
  986. ; ;
  987. ; History: ;
  988. ; ;
  989. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  990. ; Added support for the free list of global partitions. ;
  991. ; ;
  992. ; Tue Sep 23, 1986 03:58:00p -by- David N. Weise [davidw] ;
  993. ; Added this nifty comment block. ;
  994. ;-----------------------------------------------------------------------;
  995. cProc gjoin,<PUBLIC,NEAR>
  996. cBegin nogen
  997. push ax
  998. push bx
  999. dec [di].hi_count
  1000. call gdel_free
  1001. mov ax,es:[di].ga_size
  1002. mov si,es:[di].ga_prev ; who points to this block
  1003. mov es,es:[di].ga_next ; Get address of block after
  1004. if KDEBUG
  1005. mov bx, es
  1006. cmp bx, es:[di].ga_prev
  1007. jne short ok
  1008. INT3_FATAL
  1009. ok:
  1010. endif
  1011. cCall free_sel,<es:[di].ga_prev> ; Free selector being removed
  1012. mov es:[di].ga_prev,si ; one we are removing.
  1013. push es ; Change it's back link
  1014. mov es,si
  1015. pop es:[di].ga_next ; and change the forward link
  1016. inc ax ; Recompute size of block
  1017. add es:[di].ga_size,ax
  1018. pop bx
  1019. pop ax
  1020. ret
  1021. cEnd nogen
  1022. ;-----------------------------------------------------------------------;
  1023. ; gzero ;
  1024. ; ;
  1025. ; Fills the given area with zeros. ;
  1026. ; ;
  1027. ; Arguments: ;
  1028. ; BX = address of first paragraph ;
  1029. ; CX = address of last paragraph ;
  1030. ; ;
  1031. ; Returns: ;
  1032. ; BX = 0 ;
  1033. ; ;
  1034. ; Error Returns: ;
  1035. ; ;
  1036. ; Registers Preserved: ;
  1037. ; AX,DX,DI,SI,DS,ES ;
  1038. ; ;
  1039. ; Registers Destroyed: ;
  1040. ; CX ;
  1041. ; Calls: ;
  1042. ; nothing ;
  1043. ; ;
  1044. ; History: ;
  1045. ; ;
  1046. ; Tue Sep 23, 1986 04:08:55p -by- David N. Weise [davidw] ;
  1047. ; Added this nifty comment block. ;
  1048. ;-----------------------------------------------------------------------;
  1049. cProc gzero,<PUBLIC,NEAR>
  1050. cBegin nogen
  1051. ; Assumptions: on entry, BX contains selector to start of block, and is
  1052. ; for a scratch descriptor that can be modified. CX contains the # of
  1053. ; paragraphs to be zeroed.
  1054. push es ; Determine if we're running on an
  1055. SetKernelDS es ; 80286. If so, we gotta worry
  1056. test es:WinFlags,WF_CPU286 ; about 64k segments.
  1057. jz its_a_386
  1058. UnSetKernelDS es ; removes addressibility from es
  1059. push ax
  1060. push bx
  1061. push cx
  1062. push dx
  1063. push di
  1064. cld
  1065. mov es,bx ; address block with es
  1066. mov bx,cx ; bx = total # paras to zero
  1067. jcxz gzexit ; just in case...
  1068. push bx ; Say it ain't so, Joe...
  1069. xor cx,cx ; force the incoming sel/descriptor to
  1070. mov bx,cx ; a limit of 64k - it might be higher
  1071. inc cx ; which would cause set_physical_adr
  1072. cCall set_sel_limit,<es> ; to destroy following descriptors.
  1073. pop bx
  1074. jmp short gz_doit
  1075. next_64k:
  1076. push es
  1077. cCall get_physical_address,<es> ;update selector to next
  1078. inc dl ; 64k block
  1079. cCall set_physical_address,<es>
  1080. pop es ;reload it with new base
  1081. gz_doit:
  1082. mov cx,1000h ; 1000h paras = 64k bytes
  1083. cmp bx,cx
  1084. jae @f
  1085. mov cx,bx ; less than 64k left
  1086. @@:
  1087. sub bx,cx ; bx = # paras left to do
  1088. shl cx,3 ; cx = # words to zero this time
  1089. xor ax,ax
  1090. mov di,ax
  1091. rep stosw
  1092. or bx,bx ; more to do?
  1093. jnz short next_64k ; go do the next block
  1094. gzexit:
  1095. pop di
  1096. pop dx
  1097. pop cx
  1098. pop bx
  1099. pop ax
  1100. pop es
  1101. ret
  1102. ; The CPU is an 80386 or better, zero the memory a faster way...
  1103. its_a_386:
  1104. .386
  1105. push eax
  1106. push edi
  1107. push ecx
  1108. movzx ecx, cx
  1109. shl ecx, 2 ; # dwords to clear
  1110. mov es, bx
  1111. xor eax, eax
  1112. xor edi, edi
  1113. cld
  1114. rep stos dword ptr es:[edi]
  1115. pop ecx
  1116. pop edi
  1117. pop eax
  1118. pop es
  1119. ret
  1120. .286p
  1121. cEnd nogen
  1122. ;-----------------------------------------------------------------------;
  1123. ; gmarkfree ;
  1124. ; ;
  1125. ; Marks a block as free, coalesceing it with any free blocks before ;
  1126. ; or after it. This does not free any handles. ;
  1127. ; ;
  1128. ; Arguments: ;
  1129. ; SI = the first free object before this one ;
  1130. ; 0 if unknown ;
  1131. ; Ring 1 if no free list update wanted ;
  1132. ; Ring 0 if free list update required ;
  1133. ; ES:DI = block to mark as free. ;
  1134. ; DS:DI = address of global arena information structure ;
  1135. ; ;
  1136. ; Returns: ;
  1137. ; ZF = 1 if freed a fixed block ;
  1138. ; SI = 0 ;
  1139. ; ZF = 0 if freed a moveable block ;
  1140. ; SI = handle table entry ;
  1141. ; ES:DI = block freed (may have been coalesced) ;
  1142. ; ;
  1143. ; Error Returns: ;
  1144. ; ;
  1145. ; Registers Preserved: ;
  1146. ; AX,BX,CX,DX,DS ;
  1147. ; ;
  1148. ; Registers Destroyed: ;
  1149. ; none ;
  1150. ; ;
  1151. ; Calls: ;
  1152. ; gjoin ;
  1153. ; gadd_free ;
  1154. ; ;
  1155. ; History: ;
  1156. ; ;
  1157. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  1158. ; Added support for the free list of global partitions. ;
  1159. ; ;
  1160. ; Sun Nov 09, 1986 01:35:08p -by- David N. Weise [davidw] ;
  1161. ; Made the debugging version fill all free space with CCCC. ;
  1162. ; ;
  1163. ; Wed Sep 24, 1986 10:27:06p -by- David N. Weise [davidw] ;
  1164. ; Added this nifty comment block. ;
  1165. ;-----------------------------------------------------------------------;
  1166. cProc gmarkfree,<PUBLIC,NEAR>
  1167. cBegin nogen
  1168. call gadd_free
  1169. mov si,es
  1170. or si,si
  1171. jz short gmf_exit
  1172. ; Mark this block as free by clearing the owner field.
  1173. mov es:[di].ga_sig,GA_SIGNATURE
  1174. mov es:[di].ga_owner,di ; Mark as free
  1175. mov es:[di].ga_flags,0 ; For good measure.
  1176. ; Remember the handle value in DX, before setting to zero.
  1177. push dx
  1178. xor dx,dx
  1179. xchg es:[di].ga_handle,dx
  1180. ; Try to coalesce with next block, if it is free
  1181. push es:[di].ga_prev ; save previous block
  1182. mov es,es:[di].ga_next ; ES = next block
  1183. cmp es:[di].ga_owner,di ; Is it free?
  1184. jne short free2 ; No, continue
  1185. call gjoin ; Yes, coalesce with block we are freeing
  1186. free2:
  1187. pop es ; ES = previous block
  1188. cmp es:[di].ga_owner,di ; Is it free?
  1189. jne short free3 ; No, continue
  1190. mov es,es:[di].ga_next ; Yes, coalesce with block we are freeing;
  1191. call gjoin
  1192. free3:
  1193. mov si,dx ; Return 0 or handle in SI
  1194. pop dx ; restore handle
  1195. cmp es:[di].ga_owner,di ; Point to free block?
  1196. je short free4 ; Yes, done
  1197. mov es,es:[di].ga_next ; No, leave ES pointing at free block
  1198. free4:
  1199. if KDEBUG
  1200. call CCCC
  1201. endif
  1202. gmf_exit:
  1203. or si,si
  1204. ret
  1205. cEnd nogen
  1206. ;-----------------------------------------------------------------------;
  1207. ; gadd_free ;
  1208. ; ;
  1209. ; Links in the given partition into the global free list. ;
  1210. ; ;
  1211. ; Arguments: ;
  1212. ; SI = the first free object before this one ;
  1213. ; 0 if unknown ;
  1214. ; odd if no free list update wanted ;
  1215. ; DS:DI = BurgerMaster ;
  1216. ; ES:DI = free global object to add ;
  1217. ; ;
  1218. ; Returns: ;
  1219. ; ;
  1220. ; Error Returns: ;
  1221. ; ;
  1222. ; Registers Preserved: ;
  1223. ; all ;
  1224. ; ;
  1225. ; Registers Destroyed: ;
  1226. ; ;
  1227. ; Calls: ;
  1228. ; nothing ;
  1229. ; ;
  1230. ; History: ;
  1231. ; ;
  1232. ; Sun Nov 09, 1986 02:42:53p -by- David N. Weise [davidw] ;
  1233. ; Wrote it. ;
  1234. ;-----------------------------------------------------------------------;
  1235. cProc gadd_free,<PUBLIC,NEAR>
  1236. cBegin nogen
  1237. test si,1
  1238. jnz no_update_wanted
  1239. push ax
  1240. push si
  1241. push ds
  1242. mov ax,es
  1243. or ax,ax ; this happens with gmovebusy
  1244. jz gaf_exit
  1245. inc [di].gi_free_count
  1246. ;
  1247. ; For DPMI compliance, we cannot look at addresses of
  1248. ; selectors in the LDT and DPMI calls would be too slow,
  1249. ; so we scan forward from the block we are freeing,
  1250. ; looking for a free block or the sentinal and insert
  1251. ; the new block before it.
  1252. ;
  1253. smov ds, es
  1254. need_a_home_loop:
  1255. mov ds, ds:[di].ga_next
  1256. cmp ds:[di].ga_owner, di ; Free?
  1257. je found_a_home
  1258. cmp ds:[di].ga_sig, GA_ENDSIG ; Sentinal
  1259. jne need_a_home_loop
  1260. found_a_home:
  1261. mov si, ds:[di].ga_freeprev ; Fix up block after free block
  1262. mov ds:[di].ga_freeprev, es
  1263. mov es:[di].ga_freeprev,si ; Fix up free block
  1264. mov es:[di].ga_freenext,ds
  1265. mov ds,si ; Fix up block before free block
  1266. mov ds:[di].ga_freenext,es
  1267. if KDEBUG
  1268. call check_free_list
  1269. endif
  1270. gaf_exit:
  1271. pop ds
  1272. pop si
  1273. pop ax
  1274. no_update_wanted:
  1275. ret
  1276. cEnd nogen
  1277. ;-----------------------------------------------------------------------;
  1278. ; gdel_free ;
  1279. ; ;
  1280. ; Removes a partition from the global free list. ;
  1281. ; ;
  1282. ; Arguments: ;
  1283. ; DS:DI = BurgerMaster ;
  1284. ; ES:DI = arena header of partition ;
  1285. ; ;
  1286. ; Returns: ;
  1287. ; ;
  1288. ; Error Returns: ;
  1289. ; ;
  1290. ; Registers Preserved: ;
  1291. ; All ;
  1292. ; ;
  1293. ; Registers Destroyed: ;
  1294. ; ;
  1295. ; Calls: ;
  1296. ; nothing ;
  1297. ; ;
  1298. ; History: ;
  1299. ; ;
  1300. ; Sun Nov 09, 1986 02:43:26p -by- David N. Weise [davidw] ;
  1301. ; Wrote it. ;
  1302. ;-----------------------------------------------------------------------;
  1303. cProc gdel_free,<PUBLIC,NEAR>
  1304. cBegin nogen
  1305. push ax
  1306. push ds
  1307. push es
  1308. mov ds,es:[di].ga_freeprev
  1309. mov es,es:[di].ga_freenext
  1310. mov ds:[di].ga_freenext,es
  1311. mov es:[di].ga_freeprev,ds
  1312. pop es
  1313. pop ds
  1314. dec [di].gi_free_count
  1315. gfx:
  1316. pop ax
  1317. if KDEBUG
  1318. call check_free_list
  1319. endif
  1320. ret
  1321. cEnd nogen
  1322. ;-----------------------------------------------------------------------
  1323. ; GrowHeap -- this procedure grows the global heap
  1324. ;
  1325. ; Input:
  1326. ; None
  1327. ;
  1328. ; Output:
  1329. ; carry clear for success
  1330. ;
  1331. public GrowHeap
  1332. GrowHeap proc near
  1333. push si
  1334. push di
  1335. push bx
  1336. push es
  1337. xor si,si
  1338. ;
  1339. ; Request 1 MB
  1340. ;
  1341. xor ax,ax
  1342. call AllocDpmiBlock
  1343. or ax,ax
  1344. jz gh30
  1345. ;
  1346. ; Format the block
  1347. ;
  1348. or bx,bx
  1349. jnz gh10
  1350. mov si,1
  1351. gh10: mov dx,ax
  1352. call FormatHeapBlock
  1353. ;
  1354. ; Add the block to the heap
  1355. ;
  1356. call AddBlockToHeap
  1357. clc
  1358. gh20: pop es
  1359. pop bx
  1360. pop di
  1361. pop si
  1362. ret
  1363. gh30: stc
  1364. jmp gh20
  1365. GrowHeap endp
  1366. ;-----------------------------------------------------------------------
  1367. ; FormatHeapBlock -- this procedure initializes three arenas in a
  1368. ; global heap block. The first arena is marked as the heap
  1369. ; initial sentinel, the second arena is the heap free block, and
  1370. ; the third arena at the very end of the block is marked as
  1371. ; 'not there'.
  1372. ;
  1373. ; In: SI:BX - size of block in paragraphs
  1374. ; DX - selector pointing to start of block (descriptor is modified!)
  1375. ;
  1376. ; Out: AX - selector to ending 'not there' block
  1377. ; BX - zero
  1378. ; SI - selector to initial sentinel
  1379. ; DI - selector to free block arena
  1380. ; ES:BX -> initial sentinel arena
  1381. ;
  1382. ; Uses: CX, DX
  1383. public FormatHeapBlock
  1384. FormatHeapBlock proc near
  1385. ; Setup selector to first arena (the new initial sentinel)
  1386. push bx ;save # paragraphs
  1387. push si
  1388. mov bx,dx ;get physical address of start
  1389. cCall get_physical_address,<bx>
  1390. push ax ;save unaligned start address
  1391. push dx
  1392. add ax,GA_ALIGN_BYTES
  1393. adc dx,0
  1394. and ax,GA_MASK_BYTES
  1395. cCall set_physical_address,<bx>
  1396. mov si,bx ;si -> initial sentinel
  1397. mov bx,10h ;set initial selector to
  1398. xor cx,cx ; be just 1 arena long
  1399. cCall set_sel_limit,<si>
  1400. ; Setup selector to second arena (the free block)
  1401. add ax,10h+GA_ALIGN_BYTES
  1402. adc dx,0
  1403. and ax,GA_MASK_BYTES
  1404. cCall alloc_data_sel,<dx,ax,1>
  1405. mov di,ax ;di -> free block arena
  1406. ; Setup selector to the third arena ('NOT THERE' at end of heap block)
  1407. pop dx ;recover unaligned start addr
  1408. pop ax
  1409. pop cx ;recover len in paragraphs
  1410. pop bx
  1411. sub bx,1
  1412. sbb cx, 0
  1413. rept 4
  1414. shl bx,1
  1415. rcl cx,1 ;cx:bx = len in bytes
  1416. endm
  1417. add ax,bx
  1418. adc dx,cx
  1419. and ax,GA_MASK_BYTES ;dx:ax -> not there arena addr
  1420. push ax ;save not there arena address
  1421. push dx
  1422. cCall alloc_data_sel,<dx,ax,1>
  1423. ; Now fill in the arenas
  1424. mov es,ax
  1425. assumes es,nothing
  1426. xor bx,bx ;es:bx -> not there arena
  1427. mov es:[bx].ga_sig,GA_SIGNATURE
  1428. mov es:[bx].ga_owner,GA_NOT_THERE
  1429. mov es:[bx].ga_flags,bl
  1430. mov es:[bx].ga_size,bx
  1431. mov es:[bx].ga_prev,di
  1432. mov es:[bx].ga_handle,bx
  1433. mov es:[bx].ga_lrunext,bx
  1434. mov es:[bx].ga_lruprev,bx
  1435. mov es,di ;es:bx -> free block
  1436. mov es:[bx].ga_sig,GA_SIGNATURE
  1437. mov es:[bx].ga_owner,bx
  1438. mov es:[bx].ga_flags,bl
  1439. mov es:[bx].ga_prev,si
  1440. mov es:[bx].ga_next,ax
  1441. mov es:[bx].ga_handle,bx
  1442. mov es:[bx].ga_lrunext,bx
  1443. mov es:[bx].ga_lruprev,bx
  1444. pop cx ;cx:bx = address of end arena
  1445. pop bx
  1446. push ax ;save not there selector
  1447. cCall get_physical_address,<di> ;dx:ax = address of free arena
  1448. sub bx,ax
  1449. sbb cx,dx ;cx:bx = length in bytes
  1450. rept 4
  1451. shr cx,1
  1452. rcr bx,1
  1453. endm
  1454. sub bx,1
  1455. sbb cx,0 ;cx:bx = length in paragraphs
  1456. or cx, cx ; Less than 1024k?
  1457. jz @F ; yes, set correct size
  1458. xor bx, bx ; no, set bogus size
  1459. @@:
  1460. mov cx,bx
  1461. xor bx,bx
  1462. mov es:[bx].ga_size,cx ;save free block size (<1024k)
  1463. pop ax ;recover end arena selector
  1464. mov es,si ;es:bx -> initial sentinel
  1465. mov es:[bx].ga_sig,GA_SIGNATURE
  1466. mov es:[bx].ga_size,bx
  1467. mov es:[bx].ga_owner,GA_NOT_THERE
  1468. mov es:[bx].ga_flags,bl
  1469. mov es:[bx].ga_prev,si ;first.prev = self
  1470. mov es:[bx].ga_next,di
  1471. mov es:[bx].ga_handle,bx
  1472. mov es:[bx].ga_lrunext,bx
  1473. mov es:[bx].ga_lruprev,bx
  1474. ret
  1475. FormatHeapBlock endp
  1476. ;-----------------------------------------------------------------------
  1477. ;
  1478. ; In: AX - selector to ending 'not there' block
  1479. ; BX - zero
  1480. ; SI - selector to initial sentinel
  1481. ; DI - selector to free block arena
  1482. ; ES:BX -> initial sentinel arena
  1483. public AddBlockToHeap
  1484. AddBlockToHeap proc near
  1485. pusha
  1486. push bp
  1487. mov bp,sp
  1488. sub sp,8
  1489. SelFirstBlock equ word ptr [bp - 2]
  1490. SelLastBlock equ word ptr [bp - 4]
  1491. SelFreeBlock equ word ptr [bp - 6]
  1492. SelInsertBlock equ word ptr [bp - 8]
  1493. mov SelFirstBlock,si
  1494. mov SelLastBlock,ax
  1495. mov SelFreeBlock,di
  1496. ;
  1497. ; Get the physical address of this block
  1498. ;
  1499. cCall get_physical_address, <si>
  1500. mov bx,ax
  1501. mov cx,dx
  1502. xor di,di
  1503. ;
  1504. ; search for the correct place to insert it.
  1505. ;
  1506. mov si,[di].hi_first
  1507. abh20: cCall get_physical_address, <si>
  1508. cmp dx,cx
  1509. jb abh40
  1510. ja abh60
  1511. cmp ax,bx
  1512. jb abh40
  1513. ;
  1514. ; Found our spot
  1515. ;
  1516. jmp abh60
  1517. ;
  1518. ; Check the next block
  1519. ;
  1520. abh40: mov es,si
  1521. ;
  1522. ; Have we reached the end of the list?
  1523. ;
  1524. cmp si,es:[di].ga_next
  1525. mov si,es:[di].ga_next
  1526. jne abh20
  1527. ;
  1528. ; es contains the selector of the block to insert this
  1529. ; heap partition after
  1530. ;
  1531. abh60:
  1532. add [di].hi_count,3 ;three more arenas
  1533. mov ax,GA_SIGNATURE
  1534. cmp es:[di].ga_sig,GA_ENDSIG
  1535. jne abh70
  1536. ;
  1537. ; New block will be at the end of the heap
  1538. ;
  1539. mov es:[di].ga_sig,GA_SIGNATURE
  1540. mov ax,GA_ENDSIG
  1541. ;
  1542. ; make this the next block in the heap
  1543. ;
  1544. abh70: mov dx,SelFirstBlock
  1545. mov bx,es:[di].ga_next
  1546. mov es:[di].ga_next,dx
  1547. mov cx,es
  1548. mov SelInsertBlock,cx
  1549. mov es,dx
  1550. mov es:[di].ga_prev,cx
  1551. ;
  1552. ; Put the last block last
  1553. ;
  1554. mov dx,SelLastBlock
  1555. mov es,dx
  1556. mov es:[di].ga_next,bx
  1557. ;
  1558. ; If this block was last, don't update next.prev
  1559. ;
  1560. cmp ax,GA_ENDSIG
  1561. je abh75
  1562. mov es,bx
  1563. mov es:[di].ga_prev,dx
  1564. jmp abh80
  1565. ;
  1566. ; Fix the old heap end block
  1567. ;
  1568. abh75: mov es,[di].hi_last
  1569. mov es:[di].ga_owner,GA_NOT_THERE
  1570. mov es:[di].ga_sig,GA_SIGNATURE
  1571. mov es:[di].ga_size,di
  1572. mov cx,es:[di].ga_freeprev
  1573. mov es:[di].ga_freeprev,di
  1574. mov es:[di].ga_freenext,di
  1575. ;
  1576. ; Turn the new end block into a proper end block
  1577. ;
  1578. mov es,SelLastBlock
  1579. mov es:[di].ga_sig,GA_ENDSIG
  1580. mov es:[di].ga_owner,-1
  1581. mov bx,SelFreeBlock
  1582. mov es:[di].ga_freeprev,bx
  1583. mov es:[di].ga_freenext,-1
  1584. mov es:[di].ga_size,GA_ALIGN
  1585. mov ax,SelLastBlock
  1586. mov es:[di].ga_next,ax
  1587. ;
  1588. ; Fix the free list
  1589. ;
  1590. mov es,cx
  1591. mov es:[di].ga_freenext,bx
  1592. mov es,bx
  1593. mov es:[di].ga_freeprev,cx
  1594. mov ax,SelLastBlock
  1595. mov es:[di].ga_freenext,ax
  1596. ;
  1597. ; Fix the discardable code fence
  1598. ;
  1599. cCall get_physical_address, <[di].hi_last>
  1600. sub ax,[di].gi_disfence
  1601. sbb dx,[di].gi_disfence_hi
  1602. mov bx,ax
  1603. mov cx,dx
  1604. cCall get_physical_address, <SelLastBlock>
  1605. sub ax,bx
  1606. sbb dx,cx
  1607. mov [di].gi_disfence,ax
  1608. mov [di].gi_disfence_hi,dx
  1609. ;
  1610. ; Increment the free block count
  1611. ;
  1612. inc [di].gi_free_count
  1613. ;
  1614. ; Make this block the last block in the heap
  1615. ;
  1616. mov ax,SelLastBlock
  1617. mov [di].hi_last,ax
  1618. jmp abh90
  1619. ;
  1620. ; Add the free block to the free list
  1621. ;
  1622. abh80: mov es,SelFreeBlock
  1623. mov si,0
  1624. cCall gadd_free
  1625. abh90: mov sp,bp
  1626. pop bp
  1627. popa
  1628. ret
  1629. AddBlockToHeap endp
  1630. ;-----------------------------------------------------------------------;
  1631. ; AllocDpmiBlock ;
  1632. ; ;
  1633. ; Allocates a block from DPMI and stores the information in ;
  1634. ; DpmiMemory. It also allocates a selector for the beginning of ;
  1635. ; the block. ;
  1636. ; ;
  1637. ; Arguments: ;
  1638. ; ;
  1639. ; AX = size of block to allocate in paragraphs ;
  1640. ; ;
  1641. ; Returns: ;
  1642. ; AX = selector to block if allocated ;
  1643. ; BX = size of block in paragraphs ;
  1644. ; BX = zero if block is 1 megabyte in size. ;
  1645. ; ;
  1646. ; Error Returns: ;
  1647. ; AX = zero if error ;
  1648. ; ;
  1649. ;-----------------------------------------------------------------------;
  1650. public AllocDpmiBlock
  1651. AllocDpmiBlock proc near
  1652. push es
  1653. push ds
  1654. push si
  1655. push di
  1656. push cx
  1657. push bp
  1658. mov bp,sp
  1659. sub sp,30h ; space for meminfo structure
  1660. MemInfo equ [bp - 30h]
  1661. SetKernelDS
  1662. ;
  1663. ; Find an unused Dpmi Block
  1664. ;
  1665. mov si,0
  1666. mov cx,NUM_DPMI_BLOCKS - 1
  1667. adb3: cmp DpmiMemory[si].DBSel,0
  1668. je adb5
  1669. add si,size DpmiBlock
  1670. loop adb3
  1671. ;
  1672. ; Did We find one?
  1673. ;
  1674. cmp DpmiMemory[si].DBSel,0
  1675. jne adb140
  1676. ;
  1677. ; Store expected size
  1678. ;
  1679. adb5: mov DpmiMemory[si].DBSize, ax
  1680. ;
  1681. ; Convert paragraphs to bytes (if paragraphs = 0, then alloc a
  1682. ; megabyte)
  1683. ;
  1684. mov cx,ax
  1685. mov bx,10h
  1686. or cx,cx
  1687. jz adb10
  1688. mov bx,ax
  1689. shr bx,0ch
  1690. shl cx,04h
  1691. ;
  1692. ; Attempt to allocate the block
  1693. ;
  1694. adb10: push si
  1695. DPMICALL 501h
  1696. mov dx,si
  1697. pop si
  1698. jc adb100
  1699. ;
  1700. ; put information into dpmi memory list
  1701. ;
  1702. adb20: mov DpmiMemory[si].DBHandleLow,di
  1703. mov DpmiMemory[si].DBHandleHigh,dx
  1704. ;
  1705. ; Allocate a selector for the beginning of the block
  1706. ;
  1707. cCall alloc_data_sel,<bx,cx,1>
  1708. ;
  1709. ; Remember the selector
  1710. ;
  1711. mov DpmiMemory[si].DBSel,ax
  1712. ;
  1713. ; Update the number of dpmi blocks
  1714. ;
  1715. inc DpmiBlockCount
  1716. ;
  1717. ; Return the information
  1718. ;
  1719. mov bx,DpmiMemory[si].DBSize
  1720. adb40: mov sp,bp
  1721. pop bp
  1722. pop cx
  1723. pop di
  1724. pop si
  1725. pop ds
  1726. pop es
  1727. ret
  1728. ;
  1729. ; Couldn't allocate a block the size we wanted. Find the largest
  1730. ; block we can allocate
  1731. ;
  1732. adb100: mov ax,ss
  1733. mov es,ax
  1734. lea di,MemInfo
  1735. DPMICALL 500h
  1736. jc adb140
  1737. ;
  1738. ; Convert block size to paragraphs
  1739. ;
  1740. mov ax,es:[di]
  1741. mov dx,es:[di + 2]
  1742. mov bx,dx
  1743. mov cx,ax
  1744. shl dx,0ch
  1745. shr ax,4
  1746. or ax,dx
  1747. ;
  1748. ; Store expected size
  1749. ; N.B. We don't jump back into the above code, because this
  1750. ; could result in an infinite loop if something is seriously
  1751. ; wrong with DPMI.
  1752. ;
  1753. mov DpmiMemory[si].DBSize, ax
  1754. ;
  1755. ; Attempt to allocate the block
  1756. ;
  1757. push si
  1758. DPMICALL 501h
  1759. mov dx,si
  1760. pop si
  1761. jnc adb20
  1762. ;
  1763. ; We have failed to allocate the memory
  1764. ;
  1765. adb140: xor ax,ax
  1766. jmp adb40
  1767. UnsetKernelDS
  1768. AllocDpmiBlock endp
  1769. if KDEBUG
  1770. ;-----------------------------------------------------------------------;
  1771. ; CCCC ;
  1772. ; ;
  1773. ; Fills the given area with DBGFILL_FREE ;
  1774. ; ;
  1775. ; Arguments: ;
  1776. ; ES:DI = arena header of free area. ;
  1777. ; ;
  1778. ; Returns: ;
  1779. ; ;
  1780. ; Error Returns: ;
  1781. ; ;
  1782. ; Registers Preserved: ;
  1783. ; All. ;
  1784. ; ;
  1785. ; Registers Destroyed: ;
  1786. ; ;
  1787. ; Calls: ;
  1788. ; ;
  1789. ; History: ;
  1790. ; ;
  1791. ; Sun Nov 09, 1986 01:39:52p -by- David N. Weise [davidw] ;
  1792. ; Wrote it. ;
  1793. ;-----------------------------------------------------------------------;
  1794. assumes ds,nothing
  1795. assumes es,nothing
  1796. cProc CCCC,<PUBLIC,NEAR>
  1797. cBegin nogen
  1798. push ds
  1799. SetKernelDS
  1800. cmp fCheckFree,0
  1801. jnz short dont_CCCC ; not while booting
  1802. test Kernel_flags,kf_check_free
  1803. jz short dont_CCCC
  1804. push ax
  1805. push bx
  1806. push cx
  1807. push dx
  1808. push di
  1809. push es
  1810. mov bx,es:[di].ga_size
  1811. mov ax,es
  1812. call get_blotto
  1813. mov es,ax
  1814. ;;; mov cx,ss ; make sure we're not wiping
  1815. ;;; cmp cx,ax ; out the stack
  1816. ;;; jb short by_64Kb_loop
  1817. ;;; add ax,bx
  1818. ;;; cmp cx,ax
  1819. ;;; ja short by_64Kb_loop ; yes it wastes debugging bytes
  1820. ;;; jmps no_not_the_stack ; but it's readable
  1821. push bx ; Say it ain't so, Joe...
  1822. xor cx,cx ; force the incoming sel/descriptor to
  1823. mov bx,cx ; a limit of 64k - it might be higher
  1824. inc cx ; which would cause set_physical_adr
  1825. cCall set_sel_limit,<es> ; to destroy following descriptors.
  1826. pop bx
  1827. jmp short CC_doit
  1828. CC_next_64k:
  1829. push es
  1830. cCall get_physical_address,<es> ;update selector to next
  1831. inc dl ; 64k block
  1832. cCall set_physical_address,<es>
  1833. pop es ;reload it with new base
  1834. CC_doit:
  1835. mov cx,1000h ; 1000h paras = 64k bytes
  1836. cmp bx,cx
  1837. jae @f
  1838. mov cx,bx ; less than 64k left
  1839. @@:
  1840. sub bx,cx ; bx = # paras left to do
  1841. shl cx,3 ; cx = # words to CC this time
  1842. mov ax,(DBGFILL_FREE or (DBGFILL_FREE SHL 8))
  1843. xor di, di
  1844. rep stosw
  1845. or bx,bx ; more to do?
  1846. jnz short CC_next_64k ; go do the next block
  1847. no_not_the_stack:
  1848. pop es
  1849. pop di
  1850. pop dx
  1851. pop cx
  1852. pop bx
  1853. pop ax
  1854. dont_CCCC:
  1855. pop ds
  1856. ret
  1857. cEnd nogen
  1858. ;-----------------------------------------------------------------------;
  1859. ; init_free_to_CCCC ;
  1860. ; ;
  1861. ; Initializes all of the free space to zero. It speeds booting if ;
  1862. ; CCCCing is not done during boot time. ;
  1863. ; ;
  1864. ; Arguments: ;
  1865. ; none ;
  1866. ; ;
  1867. ; Returns: ;
  1868. ; ;
  1869. ; Error Returns: ;
  1870. ; ;
  1871. ; Registers Preserved: ;
  1872. ; All ;
  1873. ; ;
  1874. ; Registers Destroyed: ;
  1875. ; ;
  1876. ; Calls: ;
  1877. ; CCCC ;
  1878. ; ;
  1879. ; History: ;
  1880. ; ;
  1881. ; Wed Nov 19, 1986 09:41:58a -by- David N. Weise [davidw] ;
  1882. ; Wrote it. ;
  1883. ;-----------------------------------------------------------------------;
  1884. assumes ds,nothing
  1885. assumes es,nothing
  1886. cProc init_free_to_CCCC,<PUBLIC,NEAR>
  1887. cBegin nogen
  1888. push ds
  1889. SetKernelDS
  1890. test Kernel_flags,kf_check_free
  1891. jz short dont_init
  1892. push cx
  1893. push di
  1894. push es
  1895. xor di,di
  1896. mov ds,pGlobalHeap
  1897. UnSetKernelDS
  1898. mov cx,[di].gi_free_count
  1899. mov es,[di].hi_first
  1900. mov es,es:[di].ga_freenext
  1901. CCCC_all_loop:
  1902. call CCCC
  1903. mov es,es:[di].ga_freenext
  1904. loop CCCC_all_loop
  1905. ; get EMS land if there
  1906. mov cx,[di].gi_alt_free_count
  1907. jcxz no_alts
  1908. mov es,[di].gi_alt_first
  1909. mov es,es:[di].ga_freenext
  1910. CCCC_alt_loop:
  1911. call CCCC
  1912. mov es,es:[di].ga_freenext
  1913. loop CCCC_alt_loop
  1914. no_alts:
  1915. pop es
  1916. pop di
  1917. pop cx
  1918. dont_init:
  1919. pop ds
  1920. ret
  1921. cEnd nogen
  1922. ;-----------------------------------------------------------------------;
  1923. ; check_this_space ;
  1924. ; ;
  1925. ; Makes sure the given free space is still filled with DBGFILL_FREE ;
  1926. ; ;
  1927. ; Arguments: ;
  1928. ; ES:DI = arena header of space to check ;
  1929. ; ;
  1930. ; Returns: ;
  1931. ; ;
  1932. ; Error Returns: ;
  1933. ; ;
  1934. ; Registers Preserved: ;
  1935. ; all ;
  1936. ; ;
  1937. ; Registers Destroyed: ;
  1938. ; ;
  1939. ; Calls: ;
  1940. ; ;
  1941. ; History: ;
  1942. ; ;
  1943. ; Tue Nov 18, 1986 08:26:52p -by- David N. Weise [davidw] ;
  1944. ; Wrote it. ;
  1945. ;-----------------------------------------------------------------------;
  1946. assumes ds,nothing
  1947. assumes es,nothing
  1948. cProc check_this_space,<PUBLIC,NEAR>,<ax,bx,cx,dx,di,ds,es>
  1949. cBegin
  1950. SetKernelDS
  1951. cmp fCheckFree,0
  1952. jnz short not_while_boot
  1953. test Kernel_flags,kf_check_free
  1954. jnz short cts_check_it_out
  1955. not_while_boot:
  1956. jmps cts_ret
  1957. cts_check_it_out:
  1958. mov bx,es:[di].ga_size
  1959. mov ax,es
  1960. call get_blotto
  1961. mov es,ax
  1962. push bx ; Say it ain't so, Joe...
  1963. xor cx,cx ; force the incoming sel/descriptor to
  1964. mov bx,cx ; a limit of 64k - it might be higher
  1965. inc cx ; which would cause set_physical_adr
  1966. cCall set_sel_limit,<es> ; to destroy following descriptors.
  1967. pop bx
  1968. jmp short cts_doit
  1969. cts_next_64k:
  1970. push es
  1971. cCall get_physical_address,<es> ;update selector to next
  1972. inc dl ; 64k block
  1973. cCall set_physical_address,<es>
  1974. pop es ;reload it with new base
  1975. cts_doit:
  1976. mov cx,1000h ; 1000h paras = 64k bytes
  1977. cmp bx,cx
  1978. jae @f
  1979. mov cx,bx ; less than 64k left
  1980. @@:
  1981. sub bx,cx ; bx = # paras left to do
  1982. shl cx,3 ; cx = # words to zero this time
  1983. mov ax,(DBGFILL_FREE or (DBGFILL_FREE shl 8))
  1984. xor di, di
  1985. repz scasw ; check it out
  1986. jz short so_far_so_good
  1987. kerror 0FFh,<FREE MEMORY OVERWRITE AT >,es,di
  1988. jmps cts_ret
  1989. so_far_so_good:
  1990. or bx,bx ; more to do?
  1991. jnz short cts_next_64k ; go do the next block
  1992. cts_ret:
  1993. cEnd
  1994. ;-----------------------------------------------------------------------;
  1995. ; check_free_list ;
  1996. ; ;
  1997. ; Checks the global free list for consistency. ;
  1998. ; ;
  1999. ; Arguments: ;
  2000. ; none ;
  2001. ; ;
  2002. ; Returns: ;
  2003. ; ;
  2004. ; Error Returns: ;
  2005. ; ;
  2006. ; Registers Preserved: ;
  2007. ; All ;
  2008. ; ;
  2009. ; Registers Destroyed: ;
  2010. ; ;
  2011. ; Calls: ;
  2012. ; nothing ;
  2013. ; ;
  2014. ; History: ;
  2015. ; ;
  2016. ; Wed Oct 29, 1986 10:13:42a -by- David N. Weise [davidw] ;
  2017. ; Wrote it. ;
  2018. ;-----------------------------------------------------------------------;
  2019. assumes ds,nothing
  2020. assumes es,nothing
  2021. cProc check_free_list,<PUBLIC,NEAR>
  2022. cBegin nogen
  2023. push ax
  2024. push bx
  2025. push cx
  2026. push ds
  2027. push es
  2028. SetKernelDS
  2029. cmp fCheckFree,0
  2030. jnz short cfl_outta_here
  2031. test Kernel_flags,kf_check_free
  2032. jnz short cfl_check_it_out
  2033. cfl_outta_here:
  2034. jmp all_done
  2035. cfl_check_it_out:
  2036. mov ds,pGlobalHeap
  2037. UnSetKernelDS
  2038. mov es,[di].hi_first
  2039. mov cx,[di].gi_free_count
  2040. or cx,cx
  2041. jnz short short_relative_jumps
  2042. jmp all_done
  2043. short_relative_jumps:
  2044. mov ax,es:[di].ga_freenext
  2045. mov es,ax
  2046. check_chain_loop:
  2047. mov ds,es:[di].ga_freeprev
  2048. mov es,es:[di].ga_freenext
  2049. cmp ds:[di].ga_freenext,ax
  2050. jnz short prev_bad
  2051. mov bx,ds
  2052. cmp ax,bx
  2053. jmps prev_okay
  2054. prev_bad:
  2055. mov bx, ax
  2056. kerror 0FFh,<free_list: prev bad>,ds,bx
  2057. mov ax, bx
  2058. prev_okay:
  2059. cmp es:[di].ga_freeprev,ax
  2060. jnz short next_bad
  2061. mov bx,es
  2062. cmp ax,bx
  2063. jmps next_okay
  2064. next_bad:
  2065. mov bx, ax
  2066. kerror 0FFh,<free_list: next bad>,bx,es
  2067. next_okay:
  2068. mov ax,es
  2069. loop check_chain_loop
  2070. SetKernelDS
  2071. mov ds,pGlobalHeap
  2072. UnSetKernelDS
  2073. cmp [di].hi_last,ax
  2074. jz short all_done
  2075. mov bx, ax
  2076. kerror 0FFh,<free_list: count bad>,[di].hi_last,bx
  2077. all_done:
  2078. pop es
  2079. pop ds
  2080. pop cx
  2081. pop bx
  2082. pop ax
  2083. ret
  2084. cEnd nogen
  2085. ;-----------------------------------------------------------------------;
  2086. ; ValidateFreeSpaces ;
  2087. ; ;
  2088. ; The global free list is gone through to make sure that all free ;
  2089. ; partitions are filled with DBGFILL_FREE ;
  2090. ; ;
  2091. ; Arguments: ;
  2092. ; none ;
  2093. ; ;
  2094. ; Returns: ;
  2095. ; ;
  2096. ; Error Returns: ;
  2097. ; ;
  2098. ; Registers Preserved: ;
  2099. ; all ;
  2100. ; ;
  2101. ; Registers Destroyed: ;
  2102. ; ;
  2103. ; Calls: ;
  2104. ; ;
  2105. ; History: ;
  2106. ; ;
  2107. ; Tue Nov 18, 1986 09:46:55a -by- David N. Weise [davidw] ;
  2108. ; Wrote it. ;
  2109. ;-----------------------------------------------------------------------;
  2110. assumes ds,nothing
  2111. assumes es,nothing
  2112. cProc ValidateFreeSpaces,<PUBLIC,FAR>
  2113. cBegin nogen
  2114. push ds
  2115. SetKernelDS
  2116. test Kernel_flags,kf_check_free
  2117. jz short dont_validate
  2118. push cx
  2119. push di
  2120. push es
  2121. xor di,di
  2122. mov ds,pGlobalHeap
  2123. UnSetKernelDS
  2124. mov cx,[di].gi_free_count
  2125. mov es,[di].hi_first
  2126. mov es,es:[di].ga_freenext
  2127. jcxz empty_list
  2128. check_all_loop:
  2129. call check_this_space
  2130. mov es,es:[di].ga_freenext
  2131. loop check_all_loop
  2132. empty_list:
  2133. pop es
  2134. pop di
  2135. pop cx
  2136. dont_validate:
  2137. pop ds
  2138. ret
  2139. cEnd nogen
  2140. else
  2141. cProc ValidateFreeSpaces,<PUBLIC,FAR>
  2142. cBegin nogen
  2143. ret
  2144. cEnd nogen
  2145. endif
  2146. sEnd CODE
  2147. end