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.

835 lines
19 KiB

  1. TITLE LALLOC - Local memory allocator
  2. include kernel.inc
  3. .errnz la_prev ; This code assumes la_prev = 0
  4. externW pLocalHeap
  5. DataBegin
  6. externB Kernel_flags
  7. DataEnd
  8. sBegin CODE
  9. assumes CS,CODE
  10. externNP lalign ; LINTERF.ASM
  11. externNP lnotify ; LINTERF.ASM
  12. externNP lcompact ; LCOMPACT.ASM
  13. if KDEBUG
  14. externNP CheckLAllocBreak ; LINTERF.ASM
  15. endif
  16. ;-----------------------------------------------------------------------;
  17. ; ljoin ;
  18. ; ;
  19. ; Join two blocks together, by removing one. ;
  20. ; ;
  21. ; Arguments: ;
  22. ; BX = address of block to remove ;
  23. ; SI = address of block that points to the one to remove ;
  24. ; ;
  25. ; Returns: ;
  26. ; BX = address of block following [SI], after join ;
  27. ; Updated hi_count field in the local arena info structure ;
  28. ; ;
  29. ; Error Returns: ;
  30. ; ;
  31. ; Registers Preserved: ;
  32. ; ;
  33. ; Registers Destroyed: ;
  34. ; ;
  35. ; Calls: ;
  36. ; ;
  37. ; History: ;
  38. ; ;
  39. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  40. ; Added free list stuff. ;
  41. ; ;
  42. ; Tue Oct 14, 1986 05:20:56p -by- David N. Weise [davidw] ;
  43. ; Added this nifty comment block. ;
  44. ;-----------------------------------------------------------------------;
  45. assumes ds, nothing
  46. assumes es, nothing
  47. cProc ljoin,<PUBLIC,NEAR>
  48. cBegin nogen
  49. IncLocalStat ls_ljoin
  50. push di
  51. dec [di].hi_count ; remove free block from arena
  52. mov di,bx ; save ptr to block removing
  53. mov bx,[bx].la_next ; Get address of block after
  54. and [bx].la_prev,LA_ALIGN ; one we are removing.
  55. or [bx].la_prev,si ; Change it's back link
  56. mov [si].la_next,bx ; and change the forward link
  57. ; If it is free, remove the block at [DI] from the free list
  58. test [di].la_prev,LA_BUSY
  59. jnz join1
  60. xchg bx,di
  61. call lfreedelete ; delete from free list
  62. xchg bx,di
  63. join1:
  64. ; if the block at [SI] is free, set its new larger free block
  65. ; size. If not free, then block at [DI] is about to become part
  66. ; of the previous busy block.
  67. test [si].la_prev,LA_BUSY ; is it busy?
  68. jnz joinexit ; yes
  69. push ax
  70. mov ax,bx
  71. sub ax,si ; length of new free block
  72. mov [si].la_size,ax
  73. pop ax
  74. if KDEBUG
  75. ; Fill new free block with DBGFILL_ALLOC
  76. xchg si,bx
  77. call lfillCC
  78. xchg si,bx
  79. endif
  80. joinexit:
  81. pop di
  82. ret
  83. cEnd nogen
  84. ;-----------------------------------------------------------------------;
  85. ; lrepsetup ;
  86. ; ;
  87. ; Sets up for a block store or move of words. ;
  88. ; ;
  89. ; Arguments: ;
  90. ; CX = #bytes ;
  91. ; ;
  92. ; Returns: ;
  93. ; CX = #words ;
  94. ; ES = DS ;
  95. ; DF = 0 ;
  96. ; ;
  97. ; Error Returns: ;
  98. ; ;
  99. ; Registers Preserved: ;
  100. ; ;
  101. ; Registers Destroyed: ;
  102. ; ;
  103. ; Calls: ;
  104. ; ;
  105. ; History: ;
  106. ; ;
  107. ; Tue Oct 14, 1986 05:23:25p -by- David N. Weise [davidw] ;
  108. ; Added this nifty comment block. ;
  109. ;-----------------------------------------------------------------------;
  110. assumes ds, nothing
  111. assumes es, nothing
  112. cProc lrepsetup,<PUBLIC,NEAR>
  113. cBegin nogen
  114. shr cx,1
  115. push ds
  116. pop es
  117. cld
  118. ret
  119. cEnd nogen
  120. ;-----------------------------------------------------------------------;
  121. ; lzero ;
  122. ; ;
  123. ; Fills a block with zeros. ;
  124. ; ;
  125. ; Arguments: ;
  126. ; BX = address of last word +1 to zero ;
  127. ; CX = address of first word to zero ;
  128. ; ;
  129. ; Returns: ;
  130. ; ;
  131. ; Error Returns: ;
  132. ; ;
  133. ; Registers Preserved: ;
  134. ; ;
  135. ; Registers Destroyed: ;
  136. ; CX,ES ;
  137. ; ;
  138. ; Calls: ;
  139. ; ;
  140. ; History: ;
  141. ; ;
  142. ; Tue Oct 14, 1986 05:25:30p -by- David N. Weise [davidw] ;
  143. ; Added this nifty comment block. ;
  144. ;-----------------------------------------------------------------------;
  145. assumes ds, nothing
  146. assumes es, nothing
  147. cProc lzero,<PUBLIC,NEAR>
  148. cBegin nogen
  149. push di
  150. mov di,cx ; DI = destination
  151. sub cx,bx ; CX = - #bytes
  152. jae zero1 ; Do nothing if BX less than or equal to CX
  153. push ax
  154. neg cx
  155. xor ax,ax
  156. call lrepsetup ; Setup for stosw
  157. rep stosw ; Zero it out
  158. pop ax
  159. zero1:
  160. pop di
  161. ret
  162. cEnd nogen
  163. if KDEBUG
  164. ;-----------------------------------------------------------------------;
  165. ; lallocfill ;
  166. ; ;
  167. ; Fills a block with DBGFILL_ALLOC ;
  168. ; ;
  169. ; Arguments: ;
  170. ; BX = address of last word +1 to zero ;
  171. ; CX = address of first word to zero ;
  172. ; ;
  173. ; Registers Destroyed: ;
  174. ; CX,ES ;
  175. ; ;
  176. ;-----------------------------------------------------------------------;
  177. cProc lallocfill,<PUBLIC,NEAR>
  178. cBegin nogen
  179. push di
  180. mov di,cx ; DI = destination
  181. sub cx,bx ; CX = - #bytes
  182. jae @F ; Do nothing if BX less than or equal to CX
  183. push ax
  184. neg cx
  185. mov ax,(DBGFILL_ALLOC or (DBGFILL_ALLOC shl 8))
  186. call lrepsetup ; Setup for stosw
  187. rep stosw ; Zero it out
  188. pop ax
  189. @@:
  190. pop di
  191. ret
  192. cEnd nogen
  193. endif ;KDEBUG
  194. ;-----------------------------------------------------------------------;
  195. ; lalloc ;
  196. ; ;
  197. ; Actually allocates a local object. Called from within the local ;
  198. ; memory manager's critical section. ;
  199. ; ;
  200. ; Arguments: ;
  201. ; AX = allocations flags ;
  202. ; BX = #bytes ;
  203. ; DI = address of local arena information structure ;
  204. ; ;
  205. ; Returns: ;
  206. ; AX = data address of block allocated or NULL ;
  207. ; DX = allocation flags or size of largest free block ;
  208. ; if AX = 0 ;
  209. ; ZF = 1 if AX = 0 ;
  210. ; ;
  211. ; Error Returns: ;
  212. ; ;
  213. ; Registers Preserved: ;
  214. ; ;
  215. ; Registers Destroyed: ;
  216. ; ;
  217. ; Calls: ;
  218. ; ;
  219. ; History: ;
  220. ; ;
  221. ; Mon March 9, 1986 -by- Bob Gunderson (bobgu) ;
  222. ; Changed the search algorithm to use the free list and added calls ;
  223. ; to add/remove blocks from the free list ;
  224. ; ;
  225. ; Tue Oct 14, 1986 05:27:40p -by- David N. Weise [davidw] ;
  226. ; Added this nifty comment block. ;
  227. ;-----------------------------------------------------------------------;
  228. assumes ds, nothing
  229. assumes es, nothing
  230. cProc lalloc,<PUBLIC,NEAR>
  231. cBegin nogen
  232. if KDEBUG
  233. call CheckLAllocBreak
  234. jnc @F
  235. xor ax,ax
  236. ret
  237. @@:
  238. endif
  239. push si
  240. push ax
  241. push bx
  242. test al,LA_MOVEABLE ; Moveable?
  243. ; jnz scanbwd ; Yes, search backwards
  244. jz @F
  245. jmp scanbwd
  246. @@:
  247. IncLocalStat ls_falloc
  248. add bx,la_fixedsize ; Room for fixed header
  249. call lalign ; Get requested size in DX
  250. mov bx,[di].hi_first ; No, start with first entry
  251. ; use free list to find a block to allocate
  252. afwdloop:
  253. mov ax,[bx].la_free_next ; get next free block
  254. cmp ax,bx ; are we at end of arena ?
  255. jz afwdcmp ; yes try to compact....
  256. IncLocalStat ls_fexamine
  257. mov bx,ax
  258. cmp dx,[bx].la_size ; is it big enough?
  259. ja afwdloop ; no, loop for next
  260. ; Here when we have a block big enough.
  261. ; BX = address of block
  262. ; DX = requested size, including fixed header
  263. afwdfound:
  264. if KDEBUG
  265. ; verify the block is filled with DBGFILL_FREE
  266. call lcheckCC
  267. jz afwdfound1 ; all OK
  268. kerror ERR_LMEM,<LocalAlloc: Local free memory overwritten>
  269. afwdfound1:
  270. endif
  271. IncLocalStat ls_ffound
  272. mov ax,la_fixedsize
  273. mov cx,[bx].la_next ; mov cx,[bx].la_next
  274. sub cx,LA_MINBLOCKSIZE ; CX = as low as we will go for free
  275. mov si,bx ; Calculate address of new block
  276. add si,dx ; (current block + requested size)
  277. cmp si,cx ; Is it past the current next block
  278. ;;;;;;; jae aexit1 ; yes, use the whole block
  279. jb afwdfound2
  280. jmp aexit1
  281. afwdfound2:
  282. ; Here with two blocks.
  283. ; BX = address of existing block
  284. ; SI = address of new block to add to arena as free space
  285. IncLocalStat ls_ffoundne
  286. push bx
  287. jmp aexit
  288. afwdcmp:
  289. IncLocalStat ls_fcompact
  290. call lcompact ; End of arena. Try compacting.
  291. cmp ax,dx ; Room for requested size?
  292. jae afwdfound ; Yes, exit search loop
  293. afail: ; No, fail.
  294. push ax ; Remember size of largest free block
  295. xor bx,bx
  296. .errnz LN_OUTOFMEM ; Notify client procedure
  297. xchg ax,bx ; BX = size of largest free block
  298. mov cx,dx ; CX = size we are looking for
  299. call lnotify
  300. pop dx ; DX = size of largest free block
  301. pop bx ; BX = requested size
  302. pop ax ; AX = flags
  303. pop si ; Restore SI
  304. ; jnz lalloc ; Try again if notify procedure said to
  305. jz @F
  306. jmp lalloc
  307. @@:
  308. IncLocalStat ls_fail
  309. xor ax,ax ; O.W. return zero, with Z flag set
  310. ret
  311. scanbwd:
  312. IncLocalStat ls_malloc
  313. add bx,SIZE LocalArena ; Room for moveable header
  314. call lalign ; Get requested size in DX
  315. mov bx,[di].hi_last
  316. ; use free chain to find a block to aloocate
  317. abwdloop:
  318. IncLocalStat ls_mexamine
  319. mov ax,[bx].la_free_prev ; previous free block
  320. cmp ax,bx ; are we at beginning of arena ?
  321. jz abwdcmp ; yes try to compact....
  322. mov bx,ax
  323. cmp dx,[bx].la_size ; Room for requested size?
  324. ja abwdloop ; no, loop to previous free block
  325. jmps abwdfound ; yes, alloocate the memory
  326. ; Beginning of arena. Try compacting. If that fails then too bad
  327. abwdcmp:
  328. IncLocalStat ls_mcompact
  329. call lcompact
  330. cmp ax,dx ; Room for requested size?
  331. jb afail ; No, fail
  332. mov si,ax ; Yes, get free size in SI
  333. abwdfound:
  334. if KDEBUG
  335. ; verify the block is filled with DBGFILL_FREE
  336. call lcheckCC
  337. jz abwdfound1 ; all OK
  338. kerror ERR_LMEM,<LocalAlloc: Local free memory overwritten>
  339. abwdfound1:
  340. endif
  341. IncLocalStat ls_mfound
  342. mov ax,SIZE LocalArena
  343. mov si,[bx].la_size ; size of block found
  344. sub si,dx ; SI = size of free block = total size
  345. ; less requested size (includes header)
  346. mov cx,si ; save what's left over
  347. add si,bx ; SI = address of new block
  348. cmp cx,LA_MINBLOCKSIZE ; enough room for another?
  349. jb aexit1 ; no, use entire block
  350. push si
  351. IncLocalStat ls_mfoundne
  352. ; Here with two blocks, in following order
  353. ; BX = address of existing free block to make smaller
  354. ; SI = address of new block to add to arena as busy
  355. ; CX = address of block after new block
  356. aexit:
  357. mov cx,si
  358. xchg [bx].la_next,cx
  359. mov [si].la_prev,bx
  360. mov [si].la_next,cx
  361. ; Here with allocated block
  362. ; BX = address of found block
  363. ; SI = address of new block after found block
  364. ; CX = address of block after new block
  365. xchg si,cx ; SI = block after new block
  366. and [si].la_prev,LA_ALIGN ; CX = new block
  367. or [si].la_prev,cx ; Point to new block
  368. inc [di].hi_count ; We added an arena entry
  369. mov si,bx ; SI = previous free block
  370. mov bx,cx ; BX = new block after found block
  371. call lfreeadd ; add this new block to free list
  372. sub bx,si
  373. mov [si].la_size,bx ; set new free block size
  374. pop bx ; BX = block we are allocating
  375. aexit1:
  376. call lfreedelete ; remove this block from free list
  377. add ax,bx
  378. or byte ptr [bx].la_prev,LA_BUSY ; Mark block as busy
  379. pop dx ; Flush requested size
  380. pop dx ; Restore flags
  381. if KDEBUG
  382. test dl,LA_ZEROINIT
  383. jnz @F
  384. mov cx,ax
  385. mov bx,[bx].la_next
  386. call lallocfill
  387. jmp short aexit2
  388. @@:
  389. endif
  390. test dl,LA_ZEROINIT ; Want it zeroed?
  391. jz aexit2 ; No, all done
  392. mov cx,ax ; Yes, CX = 1st word to zero
  393. mov bx,[bx].la_next ; BX = last word+1 to zero
  394. call lzero ; Zero them
  395. aexit2:
  396. pop si
  397. or ax,ax ; Return AX points to client portion
  398. ret ; of block allocated or zero
  399. cEnd nogen
  400. ;-----------------------------------------------------------------------;
  401. ; lfree ;
  402. ; ;
  403. ; Marks a block as free, coalescing it with any free blocks before ;
  404. ; or after it. ;
  405. ; ;
  406. ; Arguments: ;
  407. ; BX = block to mark as free. ;
  408. ; DI = address of local arena information structure ;
  409. ; ;
  410. ; Returns: ;
  411. ; SI = 0 if freed a fixed block. ;
  412. ; SI = handle table entry, for moveable blocks. ;
  413. ; ZF =1 if SI = 0 ;
  414. ; Updated hi_count field in local arena information structure ;
  415. ; ;
  416. ; Error Returns: ;
  417. ; ;
  418. ; Registers Preserved: ;
  419. ; ;
  420. ; Registers Destroyed: ;
  421. ; ;
  422. ; Calls: ;
  423. ; ;
  424. ; History: ;
  425. ; ;
  426. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  427. ; Freed blocks are placed back on the free list ;
  428. ; ;
  429. ; Tue Oct 14, 1986 05:31:52p -by- David N. Weise [davidw] ;
  430. ; Added this nifty comment block. ;
  431. ;-----------------------------------------------------------------------;
  432. assumes ds, nothing
  433. assumes es, nothing
  434. cProc lfree,<PUBLIC,NEAR>
  435. cBegin nogen
  436. mov si,bx
  437. or si,si
  438. jz free4
  439. push dx
  440. push [bx].la_handle ; push possible handle
  441. ; Add block to free list
  442. push si
  443. xor si,si
  444. call lfreeadd ; add this block to free list
  445. pop si
  446. ; Clear any existing LA_BUSY and LA_MOVEABLE bits
  447. mov dx,LA_BUSY + LA_MOVEABLE
  448. and dx,[bx].la_prev
  449. xor [bx].la_prev,dx
  450. and dl,LA_MOVEABLE ; Moveable?
  451. pop dx ; restore handle
  452. jnz free1 ; Yes, return handle in DX
  453. xor dx,dx ; No, return 0 in DX
  454. free1:
  455. mov si,[bx].la_next ; SI = next block
  456. test byte ptr [si].la_prev,LA_BUSY ; Is it free?
  457. jnz free2 ; No, continue
  458. xchg bx,si
  459. call ljoin ; Yes, coelesce with block in BX
  460. mov bx,si
  461. free2:
  462. mov si,[bx].la_prev ; SI = previous block
  463. test byte ptr [si].la_prev,LA_BUSY ; Is it free?
  464. jnz free3 ; No, continue
  465. call ljoin ; Yes, coelesce with block in BX
  466. free3:
  467. mov si,dx ; Return 0 or handle in BX
  468. pop dx ; restore DX
  469. free4:
  470. or si,si ; Set Z flag if SI = zero
  471. ret
  472. cEnd nogen
  473. ;-----------------------------------------------------------------------;
  474. ; lfreeadd ;
  475. ; ;
  476. ; Links a block onto the free block chain. This routine assumes that ;
  477. ; the block to add already has the la_next and la_prev fields set ;
  478. ; to their proper values. An extended free block header is written ;
  479. ; into the block. ;
  480. ; ;
  481. ; Arguments: ;
  482. ; BX = Address of block to add to free list ;
  483. ; SI = 0 to search for insertion point, else contins the address ;
  484. ; of the previous free block. ;
  485. ; ;
  486. ; Returns: ;
  487. ; ;
  488. ; Error Returns: ;
  489. ; ;
  490. ; Registers Preserved: ;
  491. ; All are preserved ;
  492. ; ;
  493. ; Registers Destroyed: ;
  494. ; ;
  495. ; Calls: ;
  496. ; ;
  497. ; History: ;
  498. ; ;
  499. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  500. ;Initail version ;
  501. ;-----------------------------------------------------------------------;
  502. assumes ds, nothing
  503. assumes es, nothing
  504. cProc lfreeadd,<PUBLIC,NEAR>
  505. cBegin nogen
  506. push si
  507. push di
  508. push ax
  509. push cx
  510. or si,si ; need to search for insertion point?
  511. jnz lfa1 ; no
  512. ; We first need to find the previous free block so that we can insert this
  513. ; block into the proper place.
  514. mov si,ds:pLocalHeap ; get local arena info block address
  515. if KDEBUG
  516. ; Range check the insertion point
  517. cmp bx,[si].hi_first
  518. jb lfadie
  519. cmp bx,[si].hi_last
  520. jb lfaok
  521. lfadie:
  522. kerror ERR_LMEM,<lfreeadd : Invalid local heap>
  523. lfaok:
  524. endif
  525. mov si,[si].hi_first ; get first block address (free list header)
  526. lfaloop:
  527. mov ax,[si].la_free_next ; get address of next free block
  528. cmp bx,ax ; will next block be past new block?
  529. jb lfa1 ; yes, DI contains block to insert AFTER
  530. mov si,ax
  531. jmp lfaloop ; loop on next block
  532. ; At this point, BX = block to insert, SI = block to insert after
  533. lfa1:
  534. mov di,[si].la_free_next ; get next free block
  535. mov [bx].la_free_next,di ;
  536. mov [si].la_free_next,bx ; set new next block
  537. mov [bx].la_free_prev,si ; set new previous block
  538. mov [di].la_free_prev,bx ; ditto
  539. mov ax,[bx].la_next ; next block (not necessarily free)
  540. sub ax,bx
  541. mov [bx].la_size,ax ; set the size of this block
  542. if KDEBUG
  543. ; now fill the new free block with DBGFILL_ALLOC
  544. call lfillCC
  545. endif
  546. pop cx
  547. pop ax
  548. pop di
  549. pop si
  550. ret
  551. cEnd nogen
  552. ;-----------------------------------------------------------------------;
  553. ; lfreedelete ;
  554. ; ;
  555. ; Removes a specified block from the free list. This routine assums ;
  556. ; that the specified block is indeed on the free list ;
  557. ; ;
  558. ; Arguments: ;
  559. ; BX = Address of block to remove from the free list ;
  560. ; ;
  561. ; Returns: ;
  562. ; ;
  563. ; Error Returns: ;
  564. ; ;
  565. ; Registers Preserved: ;
  566. ; All are preserved ;
  567. ; ;
  568. ; Registers Destroyed: ;
  569. ; ;
  570. ; Calls: ;
  571. ; ;
  572. ; History: ;
  573. ; ;
  574. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  575. ;Initail version ;
  576. ;-----------------------------------------------------------------------;
  577. assumes ds, nothing
  578. assumes es, nothing
  579. cProc lfreedelete,<PUBLIC,NEAR>
  580. cBegin nogen
  581. push di
  582. push si
  583. mov di,[bx].la_free_prev
  584. mov si,[bx].la_free_next
  585. mov [di].la_free_next,si
  586. mov [si].la_free_prev,di
  587. pop si
  588. pop di
  589. ret
  590. cEnd nogen
  591. ;-----------------------------------------------------------------------;
  592. ; lfillCC ;
  593. ; ;
  594. ; Fills all the bytes in the specified block with DBGFILL_FREE ;
  595. ; ;
  596. ; Arguments: ;
  597. ; BX = Address of block to fill ;
  598. ; ;
  599. ; Returns: ;
  600. ; ;
  601. ; Error Returns: ;
  602. ; ;
  603. ; Registers Preserved: ;
  604. ; All are preserved ;
  605. ; ;
  606. ; Registers Destroyed: ;
  607. ; ;
  608. ; Calls: ;
  609. ; ;
  610. ; History: ;
  611. ; ;
  612. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  613. ;Initail version ;
  614. ;-----------------------------------------------------------------------;
  615. if KDEBUG
  616. assumes ds, nothing
  617. assumes es, nothing
  618. cProc lfillCC,<PUBLIC,NEAR>
  619. cBegin nogen
  620. push di
  621. push cx
  622. push ax
  623. ; if heap free checking is off, don't fill the block.
  624. mov di,pLocalHeap
  625. cmp [di].hi_check,2 ; 2 -> checkfree
  626. jb fillexit
  627. lea di,[bx].la_freefixedsize
  628. mov cx,[bx].la_next
  629. cmp cx,bx ; marker block ?
  630. jz fillexit
  631. sub cx,di
  632. mov al,DBGFILL_FREE
  633. push ds
  634. pop es
  635. cld
  636. rep stosb
  637. fillexit:
  638. pop ax
  639. pop cx
  640. pop di
  641. ret
  642. cEnd nogen
  643. endif
  644. ;-----------------------------------------------------------------------;
  645. ; lcheckCC ;
  646. ; ;
  647. ; checks all bytes in the specified block for the value DBGFILL_FREE ;
  648. ; ;
  649. ; Arguments: ;
  650. ; BX = Address of block to check ;
  651. ; ;
  652. ; Returns: ;
  653. ; ZF = 0 if block does not contain all 0CCh values, else ZF = 1 ;
  654. ; ;
  655. ; Error Returns: ;
  656. ; ;
  657. ; Registers Preserved: ;
  658. ; All are preserved ;
  659. ; ;
  660. ; Registers Destroyed: ;
  661. ; ;
  662. ; Calls: ;
  663. ; ;
  664. ; History: ;
  665. ; ;
  666. ; Mon March 9, 1987 -by- Bob Gunderson (bobgu) ;
  667. ;Initail version ;
  668. ;-----------------------------------------------------------------------;
  669. if KDEBUG
  670. assumes ds, nothing
  671. assumes es, nothing
  672. cProc lcheckCC,<PUBLIC,NEAR>
  673. cBegin nogen
  674. push si
  675. push cx
  676. push ax
  677. ; if heap checking is off, don't check the block
  678. mov si,pLocalHeap
  679. xor cx,cx ; cx == 0 for ok return
  680. cmp [si].hi_check,2
  681. jb testexit
  682. lea si,[bx].la_freefixedsize
  683. mov cx,[bx].la_next
  684. cmp cx,bx ; sentinel block ?
  685. jz testexit2 ; yes: return ZF = 1 for success
  686. sub cx,si
  687. push ds
  688. pop es
  689. cld
  690. testloop:
  691. lodsb
  692. cmp al,DBGFILL_FREE
  693. loope testloop
  694. testexit:
  695. or cx,cx ; ZF = 1 if ok, ZF = 0 if failed test
  696. testexit2:
  697. pop ax
  698. pop cx
  699. pop si
  700. ret
  701. cEnd nogen
  702. endif
  703. sEnd CODE
  704. end