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.

1744 lines
69 KiB

  1. PAGE ,132
  2. TITLE GALLOC - Global memory allocator
  3. .sall
  4. .xlist
  5. include kernel.inc
  6. include protect.inc
  7. include wowcmpat.inc
  8. .list
  9. .386
  10. DataBegin
  11. externB Kernel_flags
  12. externB fBooting
  13. externB fCheckFree
  14. externW pGlobalHeap
  15. externW Win386_Blocks
  16. externW FreeArenaCount
  17. gsearch_state_machine dw 0
  18. gsearch_compact_first dw 0
  19. public ffixedlow
  20. ffixedlow db 0
  21. DataEnd
  22. sBegin CODE
  23. assumes CS,CODE
  24. externNP gcompact
  25. externNP gmovebusy
  26. externNP gslide
  27. externNP galign
  28. externNP genter
  29. externNP gleave
  30. ifdef WOW
  31. externFP MyGetAppWOWCompatFlagsEx
  32. endif
  33. externNP gwin386discard
  34. externNP GetDPMIFreeSpace
  35. externNP InnerShrinkHeap
  36. externNP get_physical_address
  37. externNP set_physical_address
  38. externNP alloc_arena_header
  39. externNP free_arena_header
  40. ifndef WOW_x86
  41. externNP get_blotto
  42. endif
  43. externNP PreallocArena
  44. externNP DPMIProc
  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. ; EBX = #bytes ;
  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. ; ;
  92. ; History: ;
  93. ; ;
  94. ; ;
  95. ; 19-Aug-95 davehart: Win 3.1 tries to grow the heap before ;
  96. ; compacting it, for WOW we want to compact first to be a good ;
  97. ; multitasking neighbor. ;
  98. ; ;
  99. ; Wed Jul 22, 1987 11:15:19p -by- David N. Weise [davidw] ;
  100. ; Fixed BOGUS BLOCK freeing yet again. ;
  101. ; ;
  102. ; Sun May 10, 1987 11:29:38p -by- David N. Weise [davidw] ;
  103. ; Added the state machine to handle the case of wanting to search ;
  104. ; both global arenas. ;
  105. ; ;
  106. ; Sat Feb 28, 1987 06:31:11p -by- David N. Weise [davidw] ;
  107. ; Putting in support for allocating discardable code from EEMS land. ;
  108. ; ;
  109. ; Tue Dec 30, 1986 01:54:50p -by- David N. Weise [davidw] ;
  110. ; Made sure it freed any bogus blocks created. ;
  111. ; ;
  112. ; Thu Nov 20, 1986 04:00:06p -by- David N. Weise [davidw] ;
  113. ; Rewrote it use the global free list. Also made it put fixed requests ;
  114. ; as low as possible and to search again after a compact. ;
  115. ; ;
  116. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  117. ; Added support for the free list of global partitions. ;
  118. ; ;
  119. ; Tue Sep 23, 1986 04:35:39p -by- David N. Weise [davidw] ;
  120. ; Added this nifty comment block. ;
  121. ;-----------------------------------------------------------------------;
  122. assumes ds,nothing
  123. assumes es,nothing
  124. cProc gsearch,<PUBLIC,NEAR>
  125. cBegin nogen
  126. CheckKernelDS fs
  127. ReSetKernelDS fs
  128. cmp word ptr [di].gi_free_count, 96
  129. jae short compact_first
  130. mov gsearch_compact_first, 0
  131. mov gsearch_state_machine,codeOFFSET grow_heap
  132. jmp short look_again
  133. compact_first:
  134. mov gsearch_compact_first, 1
  135. mov gsearch_state_machine,codeOFFSET do_compact_nodiscard
  136. look_again:
  137. push ebx ; Save requested size
  138. push cx ; Save owner
  139. push ax ; Save flags
  140. clc ; Instead of add
  141. call galign ; Get requested size in EDX
  142. push edx ; Save adjusted requested size
  143. ; see if there is any one free space large enough for the request first
  144. mov cx,[di].gi_free_count
  145. jcxz were_hosed_from_start
  146. mov esi,[di].phi_first
  147. is_there_one:
  148. mov esi,ds:[esi].pga_freenext
  149. cmp edx,ds:[esi].pga_size
  150. jbe short got_one
  151. loop is_there_one
  152. were_hosed_from_start:
  153. jmp space_not_found
  154. got_one:
  155. mov ebx,pga_prev ; search backwards
  156. test al,GA_ALLOCHIGH
  157. jz short alloc_low
  158. ;------ allocate disc code -------
  159. public alloc_high
  160. alloc_high:
  161. mov cx,[di].gi_free_count
  162. mov esi,[di].phi_last ; Start with last entry.
  163. alloc_high_loop:
  164. mov esi,ds:[esi].pga_freeprev
  165. cmp edx,ds:[esi].pga_size
  166. jbe afound ; Yes, exit search loop
  167. loop alloc_high_loop
  168. jmp space_not_found
  169. ;------ allocate moveable ---------
  170. public alloc_low
  171. alloc_low:
  172. mov ebx,pga_next ; Search forwards.
  173. test al,GA_MOVEABLE
  174. jz short alloc_fixed
  175. call gcheckfree ; Room for requested size?
  176. jb space_not_found
  177. jmp afound
  178. ;------ allocate fixed ------------
  179. public alloc_fixed
  180. alloc_fixed:
  181. mov esi,[di].phi_first ; Start with first entry.
  182. mov cx,[di].hi_count
  183. mov esi,ds:[esi+ebx] ; Skip first sentinel
  184. ; maybe ALLOC_DOS or regular fixed.
  185. test ah, GA_ALLOC_DOS
  186. jnz alloc_fixed_loop
  187. test fBooting, 2 ; are we past KERNEL loading
  188. jnz alloc_fixed_loop ; N: give him under 1MB line
  189. ; check to see if we want old behaviour
  190. ; this is to fix some mm drivers that mmsystem.dll will load
  191. test ffixedlow, 1 ; want FIXED under 1MB?
  192. jnz alloc_fixed_loop ; Y: give him under 1MB line
  193. ; start fixed blocks > 1MB. This will leave room for GlobalDOSAllocs
  194. ; Memory < 1MB will also get used for moveable blocks as we start
  195. ; from phi_first for these. These can be moved out of the way when
  196. ; we need to alloc GA_DOS_ALLOC requests.
  197. fast_forward_to_1MB_line: ; need to store this ptr
  198. ; for speed?
  199. cmp ds:[esi].pga_address, 100000h ; > 1Mb?
  200. jae skip_not_there ; OK for fixed allocs now
  201. mov esi,ds:[esi+ebx]
  202. loop fast_forward_to_1MB_Line
  203. ; when here it means we have no free blocks > 1MB!!!
  204. ; but have a block < 1MB. space_not_found will discard
  205. ; enough to move blocks up to generate room for this fixed blk.
  206. jmp space_not_found
  207. skip_not_there:
  208. if KDEBUG
  209. cmp [esi].pga_owner, GA_NOT_THERE
  210. je @f
  211. krDebugOut <DEB_ERROR OR DEB_KrMemMan>, "NOT_THERE block not there!"
  212. @@:
  213. endif
  214. mov esi,ds:[esi+ebx]
  215. alloc_fixed_loop:
  216. push cx
  217. push esi
  218. call is_there_theoretically_enough_space
  219. cmp eax,edx
  220. jb short nope
  221. pop esi
  222. pop cx
  223. call can_we_clear_this_space
  224. jz short anext1
  225. call gcheckfree ; Yes, room for requested size?
  226. jb short anext1
  227. ; Now we have enough free space,
  228. ; slide it back as far as possible.
  229. push eax ; This is to prevent us blocking
  230. push edx ; the growth of moveable blocks.
  231. push ebx ; AND to keep pagelocked code together
  232. call PreallocArena
  233. jz short no_sliding
  234. mov ebx, pga_prev ; Sliding backwards
  235. keep_sliding:
  236. call gslide
  237. jnz keep_sliding
  238. no_sliding:
  239. pop ebx
  240. pop edx
  241. pop eax
  242. pop edx
  243. pop cx
  244. test ch, GA_ALLOC_DOS
  245. push cx
  246. push edx
  247. jz afound
  248. cmp ds:[esi].pga_address, 100000h ; > 1Mb?
  249. jb afound
  250. jmp gsearch_fail
  251. nope:
  252. or eax,eax
  253. jz short hosed_again
  254. anext:
  255. add sp, 6 ; get rid of CX, ESI on the stack
  256. anext1:
  257. mov esi,ds:[esi+ebx]
  258. loop alloc_fixed_loop
  259. jmps and_again
  260. hosed_again:
  261. pop esi
  262. pop cx
  263. and_again:
  264. ; no one space big enough, try compacting
  265. public space_not_found
  266. space_not_found:
  267. pop edx ; get adjusted size
  268. pop ax ; get flags
  269. push ax
  270. push edx
  271. ; test al,GA_ALLOCHIGH
  272. ; jnz short ask_for_what_we_need
  273. ; add edx,0400h ; ask for 1k more
  274. ; jnc short ask_for_what_we_need ; no overflow
  275. ; mov edx,-1
  276. ask_for_what_we_need:
  277. jmp gsearch_state_machine
  278. ;------------------------------
  279. public do_compact_nodiscard ; for debugging
  280. do_compact_nodiscard:
  281. mov gsearch_state_machine,codeOFFSET grow_heap
  282. ;
  283. ; Before growing the heap try compacting without
  284. ; discarding. This step isn't executed unless there
  285. ; were 96 or more free blocks at entry to gsearch.
  286. ;
  287. test ds:[di].gi_cmpflags, GA_NODISCARD
  288. jnz short dcn_nodiscard
  289. or ds:[di].gi_cmpflags, GA_NODISCARD
  290. call gcompact
  291. and ds:[di].gi_cmpflags, NOT GA_NODISCARD
  292. jmp short over_compact
  293. dcn_nodiscard:
  294. call gcompact
  295. jmp short over_compact
  296. public do_compact ; for debugging
  297. do_compact:
  298. mov gsearch_state_machine,codeOFFSET gsearch_fail
  299. ;
  300. ; If we tried compacting before and GA_NODISCARD was set,
  301. ; there is no need to compact again, since we already
  302. ; compacted with GA_NODISCARD before attempting to
  303. ; grow the heap. If GA_NODISCARD was not set, our earlier
  304. ; compact forced it on, so it's worth trying again since
  305. ; we may be able to discard enough to satisfy the request.
  306. ;
  307. cmp gsearch_compact_first, 0
  308. je short @f
  309. test ds:[di].gi_cmpflags, GA_NODISCARD
  310. jnz short gsearch_fail
  311. @@:
  312. call gcompact
  313. over_compact:
  314. pop edx
  315. pop ax
  316. pop cx
  317. pop ebx
  318. jmp look_again
  319. public grow_heap ; for debugging
  320. grow_heap:
  321. mov gsearch_state_machine,codeOFFSET do_compact
  322. push edx ; can we get the space from DPMI?
  323. call GrowHeap
  324. pop edx
  325. jnc short over_compact ; heap grew, go look again
  326. call InnerShrinkHeap ; try to give back DPMI blocks so DPMI
  327. ; mmgr can defragment its memory
  328. jz short do_compact ; heap did not shrink
  329. push edx ; gave some back, try to get it again
  330. call GrowHeap
  331. pop edx
  332. jnc short over_compact ; heap grew, go look again
  333. doomed:
  334. ;------------------------------
  335. public gsearch_fail ; for debugging
  336. gsearch_fail: ; get size of largest free block
  337. .errnz doomed-gsearch_fail
  338. xor edx,edx
  339. mov cx,[di].gi_free_count
  340. jcxz gs_failure
  341. mov esi,[di].phi_first
  342. largest_loop:
  343. mov esi,ds:[esi].pga_freenext
  344. mov eax,ds:[esi].pga_size
  345. cmp edx,eax
  346. jae short new_smaller
  347. mov edx,eax
  348. new_smaller:
  349. loop largest_loop
  350. gs_failure:
  351. pop eax ; adjusted requested size
  352. pop ax ; AX = flags
  353. pop cx ; CX = owner field
  354. pop eax ; waste requested size
  355. xor eax,eax ; Return zero, with ZF = 1
  356. ret
  357. ; Here when we have a block big enough.
  358. ; ES:DI = address of block
  359. ; AX = size of block, including header
  360. ; DX = requested size, including header
  361. ; BX = ga_prev if backwards search and ga_next if forwards search
  362. afound:
  363. mov ecx,ds:[esi].pga_size ; Use actual size of free block
  364. sub ecx,edx ; (found size - requested size)
  365. jecxz no_arena_needed
  366. call PreallocArena
  367. jnz short no_arena_needed
  368. ;
  369. ; Detect infinite loop here. If we are out of arenas, and
  370. ; the compact failed once, then another one isn't going to do much
  371. ; good.
  372. ;
  373. cmp gsearch_state_machine,codeOFFSET gsearch_fail
  374. je gsearch_fail
  375. pop edx ; get adjusted size
  376. pop ax ; get flags
  377. push ax
  378. push edx
  379. and ds:[di].gi_cmpflags, NOT (GA_NODISCARD+GA_NOCOMPACT)
  380. or ds:[di].gi_cmpflags, COMPACT_ALLOC
  381. mov edx, -1 ; Discard the world!
  382. jmp do_compact
  383. no_arena_needed:
  384. mov eax,ds:[esi].pga_freeprev
  385. call gdel_free ; remove the alloc block from freelist
  386. jecxz aexitx
  387. cmp bl,pga_prev ; Yes, scanning forwards or backwards?
  388. je short abackward ; Backwards.
  389. call gsplice ; FS:ESI = block we are allocating
  390. jmps aexit ; EDX = block to mark as free
  391. abackward:
  392. neg edx
  393. add edx,ds:[esi].pga_size ; Scanning backwards. Put extra space
  394. call gsplice
  395. xchg edx, esi
  396. jmps aexit
  397. ; Here with allocated block
  398. ; AX = data address or zero if nothing allocated
  399. ; ES:DI = address of block to mark as busy and zero init if requested
  400. ; EDX = address of block to mark as free
  401. aexitx:
  402. xor edx,edx ; Assume nothing extra to free
  403. aexit:
  404. pop ecx ; waste adjusted requested size
  405. pop cx ; Restore flags
  406. pop ds:[esi].pga_owner ; Mark block as busy with owner field value
  407. add sp, 4 ; waste requested size
  408. mov ds:[esi].pga_lruprev,edi
  409. mov ds:[esi].pga_lrunext,edi
  410. push esi
  411. mov esi, edx ; Free any extra space
  412. mov edx, eax ; Previous free block
  413. call gmarkfree
  414. pop esi
  415. mov dx, cx
  416. mov al,GA_SEGTYPE
  417. and al,dl
  418. test dh,GAH_NOTIFY
  419. jz short no_notify
  420. or al,GAH_NOTIFY
  421. no_notify:
  422. mov ds:[esi].pga_flags,al ; Store segment type bits
  423. mov eax,esi ; AX = address of client data
  424. test cl,GA_ZEROINIT ; Want it zeroed?
  425. jz short aexit1 ; No, all done
  426. push eax
  427. ifdef WOW_x86
  428. ;; On NT we try never to set selectors when we don't need to since it is a
  429. ;; slow operation - a system call. In this case we can use selector 23h
  430. ;; which points to all flat vdm memory as data
  431. push es
  432. push bx
  433. push edi
  434. mov bx,FLAT_SEL
  435. mov es,bx
  436. mov ecx,ds:[esi].pga_size ; Yes, zero paragraphs
  437. push ecx
  438. shr ecx, 2 ; # dwords to clear
  439. mov edi, ds:[esi].pga_address
  440. xor eax, eax
  441. cld
  442. rep stos dword ptr es:[edi]
  443. pop ecx
  444. pop edi
  445. pop bx
  446. pop es
  447. else
  448. cCall get_blotto
  449. mov ecx,ds:[esi].pga_size ; Yes, zero paragraphs
  450. push bx
  451. mov bx,ax ; from beginning of client data
  452. call gzero ; zero them
  453. pop bx
  454. endif; WOW_x86
  455. pop eax
  456. aexit1:
  457. or eax,eax
  458. ret ; Return AX points to client portion
  459. UnSetKernelDS FS ; of block allocated.
  460. cEnd nogen
  461. ;------------------------------------------------------------------
  462. ;
  463. ; ChangeAllocFixedBehaviour
  464. ; GlobalAlloc(FIXED) used to return address < 1MB if possible in 3.1
  465. ; It doesn't anymore in Chicago. You need to call this API if you
  466. ; want the old behaviour. Bad things will happen if you switch to old
  467. ; behaviour and forget to switch it back.
  468. ; MMSYSTEM.DLL loads some drivers that may expect this behaviour and
  469. ; they are the only callers of this fun. at the time of its writing.
  470. ; ENTRY = flags
  471. ; 0 = chicago behaviour
  472. ; 1 = win31 behaviour
  473. ; EXIT
  474. ; old bahaviour before this change (can be used to restore)
  475. ;
  476. ;------------------------------------------------------------------
  477. cProc ChangeAllocFixedBehaviour,<PUBLIC,FAR>
  478. parmW flags
  479. cBegin
  480. GENTER32
  481. CheckKernelDS FS
  482. ReSetKernelDS fs
  483. mov ax, flags
  484. xchg al, ffixedlow
  485. GLEAVE32
  486. cEnd
  487. cProc GrowHeap,<PUBLIC,NEAR>
  488. cBegin nogen
  489. CheckKernelDS FS
  490. ReSetKernelDS fs
  491. cmp FreeArenaCount, 4 ; 3 for below, 1 for a gsplice later
  492. jb short gh_fail
  493. pushad
  494. push edx ; Save requested size
  495. ; If they want more than 64k, assume they
  496. ; want a big block and just allocate that amount.
  497. cmp edx, 64*1024 ; Want more than 64k?
  498. jae short ask_for_it ; yes, just round up
  499. mov edx, 128*1024 ; no, try for 128k
  500. ask_for_it:
  501. mov ebx, edx
  502. add ebx, 4096-1 ; Round up to 4k multiple
  503. and bx, NOT (4096-1)
  504. cCall MyGetAppWOWCompatFlagsEx ; check if we need to pad it
  505. test ax, WOWCFEX_BROKENFLATPOINTER
  506. jz short @f
  507. add ebx, 4096*4 ; make it a bit bigger
  508. @@:
  509. push ebx ; Length we will ask for
  510. mov cx, bx
  511. shr ebx, 16
  512. DPMICALL 0501h ; Allocate Memory Block
  513. ; Get our memory
  514. jnc short got_more_memory
  515. pop ebx ; Toss length we asked for
  516. ; Couldn't get our 1st choice, how
  517. call GetDPMIFreeSpace ; much is available
  518. mov ebx, eax ; ebx = largest available
  519. pop edx ; Requested size
  520. cmp ebx, edx ; Enough for request?
  521. jbe SHORT gh_fail_pop
  522. push edx ; Expected on stack below
  523. push ebx ; Length we will ask for
  524. mov cx, bx
  525. shr ebx, 16
  526. DPMICALL 0501h ; Allocate Memory Block
  527. ; Get our memory
  528. jnc short got_more_memory
  529. add sp, 8 ; Toss requested size & len asked for
  530. gh_fail_pop:
  531. popad
  532. gh_fail:
  533. stc ; No chance mate!
  534. ret
  535. ; Now we have a new block
  536. ; Sort it in to the heap
  537. ; Create NOT THERE blocks to
  538. got_more_memory: ; bracket the new block
  539. inc Win386_Blocks
  540. pop edx ; Length of block allocated
  541. if KDEBUG
  542. mov eax, edx
  543. shr eax, 16
  544. krDebugOut <DEB_TRACE OR DEB_KrMemMan>, "GrowHeap: #ax#DX allocated"
  545. endif
  546. shl ebx, 16
  547. mov bx, cx ; EBX has linear address
  548. pop ecx ; Toss original length
  549. shl esi, 16
  550. mov si, di ; ESI has WIN386 handle
  551. xor edi, edi
  552. cCall alloc_arena_header,<ebx>
  553. mov ecx, eax ; First not there arena
  554. mov [ecx].pga_size, edi
  555. mov [ecx].pga_sig, GA_SIGNATURE
  556. mov [ecx].pga_owner, GA_NOT_THERE
  557. mov [ecx].pga_handle, di
  558. mov [ecx].pga_flags, di
  559. mov [ecx].pga_lrunext, esi ; Save WIN386 handle here
  560. mov [ecx].pga_lruprev, edi
  561. cCall alloc_arena_header,<ebx>
  562. mov [eax].pga_size, edx ; Free block
  563. push ebx ; Save address
  564. add edx, ebx ; Address of end of block
  565. mov ebx, eax
  566. mov [ecx].pga_next, ebx
  567. mov [ebx].pga_prev, ecx
  568. mov [ebx].pga_owner, di
  569. cCall alloc_arena_header,<edx>
  570. mov edx, eax
  571. mov [ebx].pga_next, edx
  572. mov [edx].pga_prev, ebx
  573. mov [edx].pga_size, edi
  574. mov [edx].pga_owner, GA_NOT_THERE
  575. mov [edx].pga_handle, di
  576. mov [edx].pga_flags, di
  577. mov [edx].pga_sig, GA_SIGNATURE
  578. mov [edx].pga_lrunext, edi
  579. mov [edx].pga_lruprev, edi
  580. pop eax ; Address of block
  581. sort_it:
  582. mov esi, [edi].phi_first
  583. cmp eax, [esi].pga_address ; Below start of heap?
  584. ja short sort_loop ; no, sort it in
  585. ; int 3 ; [this code never reached]
  586. mov [esi].pga_address, eax ; yes, adjust sentinel
  587. jmps link_it_in ; Sentinel now points to new block
  588. sort_loop:
  589. mov esi, [esi].pga_next
  590. cmp [esi].pga_next, esi ; At end?
  591. je short sort_found ; yes, put here
  592. cmp [esi].pga_owner, GA_NOT_THERE
  593. jne short sort_loop
  594. mov esi, [esi].pga_prev ; Will go after previous block.
  595. sort_found: ; Block will go after ESI
  596. cmp [esi].pga_next, esi ; This the sentinel?
  597. jne short link_it_in ; no, link it in
  598. mov eax, [edx].pga_address ; yes, adjust sentinel
  599. mov [esi].pga_address, eax
  600. sub eax, [di].gi_reserve ; Adjust fence
  601. mov [di].gi_disfence_lo, ax
  602. shr eax, 16
  603. mov [di].gi_disfence_hi, ax
  604. mov esi, [esi].pga_prev ; New block goes before sentinel
  605. link_it_in: ; Link it in after ESI
  606. mov [ecx].pga_prev, esi
  607. xchg [esi].pga_next, ecx
  608. mov [edx].pga_next, ecx
  609. mov [ecx].pga_prev, edx
  610. add [di].hi_count, 3 ; Three more entries in heap
  611. mov esi, ebx
  612. xor edx, edx
  613. call gmarkfree ; To be picked up next time around
  614. popad
  615. clc
  616. ret
  617. UnSetKernelDS FS
  618. cEnd nogen
  619. ; Input - DWORD - Old Arena offset from burgermaster
  620. ;
  621. ; Output - None
  622. cProc FreeHeapDib,<PUBLIC,FAR>
  623. parmD OldArena
  624. cBegin
  625. CheckKernelDS FS
  626. ReSetKernelDS fs
  627. ; Make sure arena before and after are GA_NOT_THERE
  628. mov ebx,OldArena
  629. mov edx,ds:[ebx].pga_prev
  630. cmp ds:[edx].pga_owner,GA_NOT_THERE
  631. jne short fhd5
  632. mov ecx,ds:[ebx].pga_next
  633. cmp ds:[ecx].pga_owner,GA_NOT_THERE
  634. je short fhd7
  635. fhd5:
  636. if KDEBUG
  637. krDebugOut <DEB_TRACE OR DEB_KrMemMan>, "FreeHeapDIB: Corrupt DIB Block"
  638. endif
  639. fhd7:
  640. ;Free all the three arenas. First fixup the arena list.
  641. ; edx - First GA_NOT_THERE arena
  642. ; ebx - Actual DIB arean
  643. ; ecx - Last GA_NOT_THERE arena
  644. mov eax,ds:[edx].pga_prev
  645. mov ebx,ds:[ecx].pga_next
  646. mov ds:[eax].pga_next,ebx
  647. mov ds:[ebx].pga_prev,eax
  648. mov ds:[edx].pga_handle,0
  649. cCall free_arena_header,<edx>
  650. mov ds:[ecx].pga_handle,0
  651. cCall free_arena_header,<ecx>
  652. mov edx,OldArena
  653. mov ds:[edx].pga_handle,0
  654. cCall free_arena_header,<edx>
  655. xor di,di
  656. sub [di].hi_count, 3 ; Three less entries in heap
  657. dec Win386_Blocks
  658. UnSetKernelDS FS
  659. cEnd
  660. ; Input - DWORD - Dib Address
  661. ; DWORD - Old Arena offset from burgermaster
  662. ;
  663. ; Output - eax = new arena if operation successful
  664. ; eax = NULL if operation failed
  665. cProc GrowHeapDib,<PUBLIC,FAR>
  666. parmD OldArena
  667. parmD NewAddress
  668. cBegin
  669. CheckKernelDS FS
  670. ReSetKernelDS fs
  671. cmp FreeArenaCount, 4 ; 3 for below, 1 for a gsplice later
  672. jae short ghd_start
  673. xor eax,eax
  674. ret
  675. ; Now we have a new block. Sort it in to the heap. Create
  676. ; NOT THERE blocks as well.
  677. ghd_start:
  678. inc Win386_Blocks
  679. mov ebx,OldArena
  680. mov edx,ds:[ebx].pga_size ; Length of block
  681. if KDEBUG
  682. mov eax, edx
  683. shr eax, 16
  684. krDebugOut <DEB_TRACE OR DEB_KrMemMan>, "GrowHeapDIB: #ax#DX allocated"
  685. endif
  686. mov ebx,NewAddress ; Ebx is the address of new block
  687. mov esi, ebx ; ESI has WIN386 handle
  688. xor edi, edi
  689. cCall alloc_arena_header,<ebx>
  690. mov ecx, eax ; First not there arena
  691. mov [ecx].pga_size, edi
  692. mov [ecx].pga_sig, GA_SIGNATURE
  693. mov [ecx].pga_owner, GA_NOT_THERE
  694. mov [ecx].pga_handle, di
  695. mov [ecx].pga_flags, di
  696. mov [ecx].pga_lrunext, esi ; Save WIN386 handle here
  697. mov [ecx].pga_lruprev, edi
  698. cCall alloc_arena_header,<ebx>
  699. mov [eax].pga_size, edx ; DIB block
  700. push ebx ; Save address
  701. add edx, ebx ; Address of end of block
  702. mov ebx, eax
  703. mov [ecx].pga_next, ebx
  704. mov [ebx].pga_prev, ecx
  705. push ecx
  706. mov ecx,OldArena
  707. mov ax, [ecx].pga_handle
  708. mov [ebx].pga_handle,ax
  709. mov ax, [ecx].pga_owner
  710. mov [ebx].pga_owner,ax
  711. mov al, [ecx].pga_count
  712. mov [ebx].pga_count,al
  713. inc [ebx].pga_count ; make sure it doesn't move
  714. mov al, [ecx].pga_pglock
  715. mov [ebx].pga_pglock,al
  716. mov al, [ecx].pga_flags
  717. mov [ebx].pga_flags,al
  718. mov al, [ecx].pga_selcount
  719. mov [ebx].pga_selcount,al
  720. mov [ebx].pga_lrunext, edi
  721. mov [ebx].pga_lruprev, edi
  722. pop ecx
  723. cCall alloc_arena_header,<edx>
  724. mov edx, eax
  725. mov [ebx].pga_next, edx
  726. mov [edx].pga_prev, ebx
  727. mov [edx].pga_size, edi
  728. mov [edx].pga_owner, GA_NOT_THERE
  729. mov [edx].pga_handle, di
  730. mov [edx].pga_flags, di
  731. mov [edx].pga_sig, GA_SIGNATURE
  732. mov [edx].pga_lrunext, edi
  733. mov [edx].pga_lruprev, edi
  734. pop eax ; Address of block
  735. mov esi, [edi].phi_first
  736. cmp eax, [esi].pga_address ; Below start of heap?
  737. ja short ghd_sort_loop ; no, sort it in
  738. ; int 3 ; [this code never reached]
  739. mov [esi].pga_address, eax ; yes, adjust sentinel
  740. jmps ghd_link_it_in ; Sentinel now points to new block
  741. ghd_sort_loop:
  742. mov esi, [esi].pga_next
  743. cmp [esi].pga_next, esi ; At end?
  744. je short ghd_sort_found ; yes, put here
  745. cmp [esi].pga_owner, GA_NOT_THERE
  746. jne short ghd_sort_loop
  747. mov esi, [esi].pga_prev ; Will go after previous block.
  748. ghd_sort_found: ; Block will go after ESI
  749. cmp [esi].pga_next, esi ; This the sentinel?
  750. jne short ghd_link_it_in ; no, link it in
  751. mov eax, [edx].pga_address ; yes, adjust sentinel
  752. mov [esi].pga_address, eax
  753. sub eax, [di].gi_reserve ; Adjust fence
  754. mov [di].gi_disfence_lo, ax
  755. shr eax, 16
  756. mov [di].gi_disfence_hi, ax
  757. mov esi, [esi].pga_prev ; New block goes before sentinel
  758. ghd_link_it_in: ; Link it in after ESI
  759. mov [ecx].pga_prev, esi
  760. xchg [esi].pga_next, ecx
  761. mov [edx].pga_next, ecx
  762. mov [ecx].pga_prev, edx
  763. add [di].hi_count, 3 ; Three more entries in heap
  764. mov eax,ebx
  765. UnSetKernelDS FS
  766. cEnd
  767. ;-----------------------------------------------------------------------;
  768. ; is_there_theoretically_enough_space
  769. ;
  770. ; Starting at the given arena checks to see if there are enough
  771. ; continuous free and unlocked moveable blocks.
  772. ;
  773. ; Entry:
  774. ; CX = arenas to search
  775. ; EDX = size requested
  776. ; DS = BurgerMaster
  777. ; FS:ESI = arena to start from
  778. ;
  779. ; Returns:
  780. ; EAX = 0 => not enough space and no more memory left to search
  781. ; EAX = 1 => not enough space in this block, but maybe....
  782. ; otherwise
  783. ; EAX = size of block
  784. ;
  785. ; Registers Destroyed:
  786. ; CX,ESI
  787. ;
  788. ; Registers Preserved:
  789. ; BX,DX,DI,ES
  790. ;
  791. ; History:
  792. ; Mon 05-Sep-1988 15:21:14 -by- David N. Weise [davidw]
  793. ; Moved it here from gsearch so that grealloc could use it as well.
  794. ;-----------------------------------------------------------------------;
  795. assumes ds,nothing
  796. assumes es,nothing
  797. cProc is_there_theoretically_enough_space,<PUBLIC,NEAR>
  798. cBegin nogen
  799. xor eax,eax
  800. ittes:
  801. cmp ds:[esi].pga_owner,di
  802. jne short is_it_moveable
  803. add eax,ds:[esi].pga_size
  804. push ebx
  805. push eax
  806. mov bx,word ptr [di].gi_disfence_hi ; See if begin of reserve area
  807. shl ebx, 16
  808. mov bx,word ptr [di].gi_disfence_lo ; is above end of free block
  809. mov eax, ds:[esi].pga_address
  810. add eax, ds:[esi].pga_size ; Address of end of free block
  811. sub eax,ebx
  812. ja short ittes_above_fence ; All below fence?
  813. ittes_below_fence:
  814. pop eax ; yes, we can use it
  815. pop ebx
  816. jmps this_ones_free
  817. ittes_above_fence:
  818. cmp eax, ds:[di].gi_reserve
  819. jae ittes_below_fence
  820. mov ebx, eax ; portion above the fence
  821. pop eax ; Total size so far
  822. sub eax,ebx ; No, Reduce apparent size of free block
  823. pop ebx
  824. cmp eax,edx
  825. jae short theoretically_enough
  826. jmps absolutely_not
  827. is_it_moveable:
  828. cmp ds:[esi].pga_owner,GA_NOT_THERE ; Against end of heap partition?
  829. je short theoretically_not ; no room here.
  830. test ds:[esi].pga_handle,GA_FIXED ; See if movable.
  831. jnz short theoretically_not
  832. cmp ds:[esi].pga_count,0
  833. jne short theoretically_not ; See if locked.
  834. add eax,ds:[esi].pga_size
  835. this_ones_free:
  836. cmp eax,edx
  837. jae short theoretically_enough
  838. mov esi,ds:[esi].pga_next
  839. loop ittes
  840. ; For the case of gsearch we should never get here for two reasons.
  841. ; 1) It should be impossible to have no discardable code loaded, in
  842. ; this case we would have failed in the above loop. 2) We checked
  843. ; at the very start for a free block somewhere that could have
  844. ; satisfied the request. In our mucking around to load as low as
  845. ; possible we destroyed this free block and we did not produce a free
  846. ; block we could use. However we know from debugging code in 2.03
  847. ; that this happens extremely rarely. Because of the rareness of
  848. ; this event we will not try to recover, instead we simply fail the call.
  849. absolutely_not:
  850. mov eax,-1 ; return EAX = 0
  851. theoretically_not:
  852. inc eax ; DX is even, => cmp the same.
  853. theoretically_enough:
  854. ret
  855. cEnd nogen
  856. ;-----------------------------------------------------------------------;
  857. ; can_we_clear_this_space
  858. ;
  859. ; Attempts to make a free space starting at the address moved in.
  860. ; To do this it moves moveable out of the area. The only subtlety
  861. ; involves a free block that stradles the end of wanted area. This
  862. ; may get broken into two pieces, the lower piece gets temporary marked
  863. ; as allocated and BOGUS, the upper piece will remain free.
  864. ;
  865. ; Entry:
  866. ; CX = max number of blocks to look at
  867. ; EDX = size wanted in bytes
  868. ; DS = BurgerMaster
  869. ; FS:ESI = beginning arena
  870. ;
  871. ; Returns:
  872. ; ZF = 0
  873. ; FS:ESI points to free space
  874. ; ZF = 1
  875. ; couldn't free the space up
  876. ;
  877. ; Registers Destroyed:
  878. ; AX,SI
  879. ;
  880. ; History:
  881. ; Mon 05-Sep-1988 16:48:31 -by- David N. Weise [davidw]
  882. ; Moved it out of gsearch so that grealloc could use it.
  883. ;-----------------------------------------------------------------------;
  884. assumes ds,nothing
  885. assumes es,nothing
  886. cProc can_we_clear_this_space,<PUBLIC,NEAR>
  887. cBegin nogen
  888. CheckKernelDS FS
  889. ReSetKernelDS FS
  890. push ecx
  891. push esi
  892. cmp di,[di].gi_free_count ; any free blocks?
  893. jz short cwcts_fail
  894. mov eax, esi ; Beginning of space we want.
  895. cmp di,ds:[esi].pga_owner ; Is it free?
  896. jnz short can_we_move_it
  897. mov ecx,edx
  898. cmp ecx,ds:[esi].pga_size
  899. ja short asdf
  900. or eax,eax ; return ZF = 0
  901. cwcts_fail:
  902. pop esi
  903. pop ecx
  904. ret
  905. asdf: mov esi,ds:[esi].pga_next
  906. public can_we_move_it
  907. can_we_move_it:
  908. push ebx
  909. push ecx
  910. push edx
  911. push esi
  912. cmp ds:[esi].pga_owner,GA_BOGUS_BLOCK
  913. jnz short not_bogus
  914. xor edx,edx
  915. call gmarkfree
  916. jmp restart
  917. not_bogus:
  918. mov ebx, ds:[eax].pga_address
  919. add ebx, edx ; EBX is the end of the space we want
  920. mov cx,[di].gi_free_count
  921. mov edx,ds:[esi].pga_size ; Yes, try to find a place for the
  922. mov esi,[di].phi_first ; moveable block
  923. look_loop:
  924. call PreAllocArena ; Needed for gmovebusy or gsplice
  925. jz couldnt_clear_it
  926. mov esi,ds:[esi].pga_freenext
  927. push esi
  928. mov esi, ds:[esi].pga_address
  929. cmp esi, ds:[eax].pga_address ; It defeats our purpose to move the
  930. jb short check_this_out ; block to a free space we want.
  931. cmp esi, ebx
  932. jb short is_there_hope
  933. check_this_out:
  934. pop esi
  935. push eax
  936. call gcheckfree
  937. push ecx
  938. jb short inopportune_free_space
  939. pop ecx
  940. pop eax
  941. pop edx ; EDX = moveable block for gmovebusy
  942. mov ebx,pga_next
  943. call gmovebusy ; Move moveable block out of the way
  944. mov esi,edx ; Replace the ESI on the stack,
  945. ; the free block may have grown
  946. ; downward with the gmovebusy.
  947. pop edx
  948. pop ecx
  949. pop ebx
  950. pop ecx ; WAS pop esi but esi set above now
  951. pop ecx
  952. jmp can_we_clear_this_space
  953. inopportune_free_space:
  954. pop ecx
  955. pop eax
  956. loop look_loop
  957. jmps couldnt_clear_it
  958. public is_there_hope
  959. is_there_hope:
  960. pop esi
  961. push eax
  962. push ecx
  963. mov ecx, ds:[esi].pga_address
  964. add ecx, ds:[esi].pga_size ; ECX end of block
  965. mov ax, [di].gi_disfence_hi
  966. shl eax, 16
  967. mov ax, [di].gi_disfence_lo ; EAX == fence
  968. sub eax, ecx ; Fence - End
  969. jae short below_reserved ; Block is below fence
  970. neg eax ; End - Fence
  971. cmp eax, ds:[di].gi_reserve
  972. jae short below_reserved ; Block is above reserved
  973. sub ecx, eax ; End - (End - Fence)
  974. ; Gives Fence in ECX
  975. below_reserved:
  976. sub ecx, ebx ; Adjust size of free block
  977. jbe inopportune_free_space ; No room here
  978. overlap:
  979. cmp ecx,edx ; Is it big enough?
  980. jbe short inopportune_free_space
  981. mov edx, ebx
  982. sub edx, ds:[esi].pga_address ; Calculate overlap
  983. pop ecx
  984. pop eax
  985. ; cut off the first piece for the original alloc
  986. push ds:[esi].pga_freeprev
  987. call gdel_free
  988. call gsplice
  989. ; DS:ESI = addr of block to mark as busy, FS:EDX = addr of block to mark as free
  990. mov ds:[esi].pga_owner,GA_BOGUS_BLOCK
  991. mov ds:[esi].pga_lruprev,edi
  992. mov ds:[esi].pga_lrunext,edi
  993. mov esi, edx
  994. pop edx ; previous free block
  995. call gmarkfree ; Free any extra space
  996. restart:
  997. pop edx ; WAS pop es
  998. pop edx
  999. pop ecx
  1000. pop ebx
  1001. pop esi
  1002. pop ecx
  1003. jmp can_we_clear_this_space
  1004. ; If here then failure! see if we made a bogus block!
  1005. couldnt_clear_it:
  1006. pop esi ; recover block we wanted moved
  1007. check_again:
  1008. mov edx,ds:[esi].pga_next
  1009. cmp edx, ds:[edx].pga_next ; At end of arenas?
  1010. je short no_bogus_block ; Yes, let's go
  1011. cmp ds:[edx].pga_address, ebx ; EBX points to where bogus block
  1012. ja short no_bogus_block ; would be.
  1013. je short is_it_bogus
  1014. mov esi,edx
  1015. jmps check_again
  1016. is_it_bogus:
  1017. cmp ds:[esi].pga_owner,GA_BOGUS_BLOCK
  1018. jnz short no_bogus_block
  1019. xor edx,edx
  1020. call gmarkfree
  1021. no_bogus_block:
  1022. if KDEBUG
  1023. mov cx,[di].hi_count
  1024. mov esi,[di].phi_first
  1025. bogus_all:
  1026. cmp ds:[esi].pga_owner,GA_BOGUS_BLOCK
  1027. jnz short not_me
  1028. int 3
  1029. not_me: mov esi,ds:[esi].pga_next
  1030. loop bogus_all
  1031. endif
  1032. pop edx
  1033. pop ecx
  1034. pop ebx
  1035. pop esi
  1036. pop ecx
  1037. xor eax,eax ; return ZF = 1
  1038. ret
  1039. UnSetKernelDS FS
  1040. cEnd nogen
  1041. ;-----------------------------------------------------------------------;
  1042. ; gcheckfree ;
  1043. ; ;
  1044. ; Checks the size of the passed free block against the passed desired ;
  1045. ; size, making sure that the limitations of the code reserve area are ;
  1046. ; not violated for objects other than discardable code. It also checks ;
  1047. ; for Phantoms. ;
  1048. ; ;
  1049. ; Arguments: ;
  1050. ; FS:ESI = address of free block ;
  1051. ; DX = #bytes needed ;
  1052. ; DS:DI = address of global arena information structure ;
  1053. ; ;
  1054. ; Returns: ;
  1055. ; CF = 0 block big enough ;
  1056. ; EAX = apparent size of free block ;
  1057. ; ;
  1058. ; Error Returns: ;
  1059. ; none ;
  1060. ; ;
  1061. ; Registers Preserved: ;
  1062. ; All ;
  1063. ; ;
  1064. ; Registers Destroyed: ;
  1065. ; ;
  1066. ; Calls: ;
  1067. ; nothing ;
  1068. ; ;
  1069. ; History: ;
  1070. ; ;
  1071. ; Thu 27-Apr-1989 10:38:05 -by- David N. Weise [davidw] ;
  1072. ; Fixed this to work in pmode. ;
  1073. ; ;
  1074. ; Thu Apr 02, 1987 10:45:22p -by- David N. Weise [davidw] ;
  1075. ; Added Phantom support. ;
  1076. ; ;
  1077. ; Tue Sep 23, 1986 05:54:51p -by- David N. Weise [davidw] ;
  1078. ; Added this nifty comment block. ;
  1079. ;-----------------------------------------------------------------------;
  1080. cProc gcheckfree,<PUBLIC,NEAR>
  1081. cBegin nogen
  1082. mov eax,ds:[esi].pga_size ; Compute size of free block
  1083. test byte ptr [di].gi_cmpflags,GA_DISCCODE
  1084. jnz short gcftest ; Discardable code not restricted
  1085. push ebx
  1086. mov ebx, [di].phi_last ; Last sentinel
  1087. mov ebx, ds:[ebx].pga_address
  1088. cmp ebx, ds:[esi].pga_address ; Above sentinel?
  1089. jbe short gcftest1 ; yes, not in reserved area!
  1090. push eax
  1091. mov bx,word ptr [di].gi_disfence_hi ; See if begin of reserve area
  1092. shl ebx, 16
  1093. mov bx,word ptr [di].gi_disfence_lo ; is above end of free block
  1094. add eax, ds:[esi].pga_address ; EAX address of end of block
  1095. sub ebx, eax
  1096. pop eax
  1097. jae short gcftest1 ; Yes, return actual size of free block
  1098. neg ebx
  1099. sub eax,ebx ; No, Reduce apparent size of free block
  1100. ja short gcftest1 ; Is it more than what is free?
  1101. xor eax,eax ; Yes, then apparent size is zero
  1102. ; Nothing left, set apparent size to 0
  1103. gcftest1:
  1104. pop ebx
  1105. jmps gcftest
  1106. gcfrsrv1: ; Yes, then apparent size is zero
  1107. xor eax,eax ; Nothing left, set apparent size to 0
  1108. gcftest:
  1109. cmp eax,edx ; Return results of the comparison
  1110. ret
  1111. cEnd nogen
  1112. ;-----------------------------------------------------------------------;
  1113. ; gsplice [should be named gslice, ;
  1114. ; since splice means combine two into one - donc] ;
  1115. ; ;
  1116. ; Splits one block into two. ;
  1117. ; ;
  1118. ; Arguments: ;
  1119. ; EDX = size in bytes of new block to make ;
  1120. ; DS:ESI = address of existing block ;
  1121. ; DS:DI = address of global arena information structure ;
  1122. ; ;
  1123. ; Returns: ;
  1124. ; EDX = address of new block
  1125. ; ;
  1126. ; Error Returns: ;
  1127. ; nothing ;
  1128. ; ;
  1129. ; Registers Preserved: ;
  1130. ; AX,BX,DX,DI,DS,ES ;
  1131. ; ;
  1132. ; Registers Destroyed: ;
  1133. ; CX ;
  1134. ; ;
  1135. ; Calls: ;
  1136. ; nothing ;
  1137. ; History: ;
  1138. ; ;
  1139. ; Tue Sep 23, 1986 03:50:30p -by- David N. Weise [davidw] ;
  1140. ; Added this nifty comment block. ;
  1141. ;-----------------------------------------------------------------------;
  1142. cProc gsplice,<PUBLIC,NEAR>,<EAX,EBX>
  1143. cBegin
  1144. mov ebx,ds:[esi].pga_size
  1145. sub ebx,edx ; get size of 2nd new block made
  1146. mov eax, ds:[esi].pga_address
  1147. add eax, edx
  1148. cCall alloc_arena_header,<eax>
  1149. inc [di].hi_count ; Adding new arena entry
  1150. mov ecx, eax
  1151. xchg ds:[esi].pga_next,ecx ; and old.next = new
  1152. mov ds:[ecx].pga_prev,eax ; [old old.next].prev = new
  1153. mov ds:[eax].pga_next,ecx ; new.next = old old.next
  1154. mov ds:[eax].pga_prev,esi
  1155. mov ds:[eax].pga_size,ebx
  1156. mov ds:[eax].pga_sig,GA_SIGNATURE
  1157. mov ds:[eax].pga_owner,di ; Zero owner & handle fields
  1158. mov ds:[eax].pga_flags,0 ; For good measure.
  1159. mov ds:[eax].pga_handle,di
  1160. mov ds:[esi].pga_size,edx
  1161. mov edx, eax
  1162. gsplice_ret:
  1163. cEnd
  1164. ;-----------------------------------------------------------------------;
  1165. ; gjoin ;
  1166. ; ;
  1167. ; Merges a block into his previous neighbor. ;
  1168. ; ;
  1169. ; Arguments: ;
  1170. ; FS:ESI = address of block to remove ;
  1171. ; DS:DI = address of global arena information structure ;
  1172. ; ;
  1173. ; Returns: ;
  1174. ; nothing ;
  1175. ; ;
  1176. ; Error Returns: ;
  1177. ; nothing ;
  1178. ; ;
  1179. ; Registers Preserved: ;
  1180. ; AX,BX,CX,DX,DI,SI,DS,ES ;
  1181. ; ;
  1182. ; Registers Destroyed: ;
  1183. ; SI ;
  1184. ; ;
  1185. ; Calls: ;
  1186. ; gdel_free ;
  1187. ; ;
  1188. ; History: ;
  1189. ; ;
  1190. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  1191. ; Added support for the free list of global partitions. ;
  1192. ; ;
  1193. ; Tue Sep 23, 1986 03:58:00p -by- David N. Weise [davidw] ;
  1194. ; Added this nifty comment block. ;
  1195. ;-----------------------------------------------------------------------;
  1196. cProc gjoin,<PUBLIC,NEAR>
  1197. cBegin nogen
  1198. if KDEBUG
  1199. cmp esi, ds:[esi].pga_prev
  1200. jne short ok
  1201. int 3
  1202. int 3
  1203. ok:
  1204. endif
  1205. push eax ; assumes one is on freelist
  1206. push edx
  1207. dec [di].hi_count
  1208. call gdel_free
  1209. mov eax,ds:[esi].pga_size
  1210. mov edx,ds:[esi].pga_next ; Get address of block after
  1211. mov esi,ds:[esi].pga_prev ; Get address of block before
  1212. cCall free_arena_header,<ds:[edx].pga_prev> ; Free arena being removed
  1213. mov ds:[edx].pga_prev,esi ; Fix up block after
  1214. mov ds:[esi].pga_next, edx ; and the one before
  1215. add ds:[esi].pga_size,eax ; Recompute size of block
  1216. pop edx
  1217. pop eax
  1218. ret
  1219. cEnd nogen
  1220. ;-----------------------------------------------------------------------;
  1221. ; gzero ;
  1222. ; ;
  1223. ; Fills the given area with zeros. ;
  1224. ; ;
  1225. ; Arguments: ;
  1226. ; BX = address of first paragraph ;
  1227. ; ECX = Bytes to clear ;
  1228. ; ;
  1229. ; Returns: ;
  1230. ; BX = 0 ;
  1231. ; ;
  1232. ; Error Returns: ;
  1233. ; ;
  1234. ; Registers Preserved: ;
  1235. ; AX,DX,DI,SI,DS,ES ;
  1236. ; ;
  1237. ; Registers Destroyed: ;
  1238. ; CX ;
  1239. ; Calls: ;
  1240. ; nothing ;
  1241. ; ;
  1242. ; History: ;
  1243. ; ;
  1244. ; Tue Sep 23, 1986 04:08:55p -by- David N. Weise [davidw] ;
  1245. ; Added this nifty comment block. ;
  1246. ;-----------------------------------------------------------------------;
  1247. cProc gzero,<PUBLIC,NEAR>
  1248. cBegin nogen
  1249. ; Assumptions: on entry, BX contains selector to start of block, and is
  1250. ; for a scratch descriptor that can be modified. ECX contains the # of
  1251. ; bytes to be zeroed.
  1252. push es
  1253. push eax
  1254. push edi
  1255. push ecx
  1256. shr ecx, 2 ; # dwords to clear
  1257. mov es, bx
  1258. xor eax, eax
  1259. xor edi, edi
  1260. cld
  1261. rep stos dword ptr es:[edi]
  1262. pop ecx
  1263. pop edi
  1264. pop eax
  1265. pop es
  1266. ret
  1267. cEnd nogen
  1268. ;-----------------------------------------------------------------------;
  1269. ; gmarkfree ;
  1270. ; ;
  1271. ; Marks a block as free, coalesceing it with any free blocks before ;
  1272. ; or after it. This does not free any handles. ;
  1273. ; ;
  1274. ; Arguments: ;
  1275. ; EDX = the first free object before this one ;
  1276. ; 0 if unknown ;
  1277. ; Ring 1 if no free list update wanted ;
  1278. ; Ring 0 if free list update required ;
  1279. ; FS:ESI = block to mark as free. ;
  1280. ; DS:DI = address of global arena information structure ;
  1281. ; ;
  1282. ; Returns: ;
  1283. ; ZF = 1 if freed a fixed block ;
  1284. ; DX = 0 ;
  1285. ; ZF = 0 if freed a moveable block ;
  1286. ; DX = handle table entry ;
  1287. ; FS:ESI = block freed (may have been coalesced) ;
  1288. ; ;
  1289. ; Error Returns: ;
  1290. ; ;
  1291. ; Registers Preserved: ;
  1292. ; AX,BX,CX,DX,DS ;
  1293. ; ;
  1294. ; Registers Destroyed: ;
  1295. ; none ;
  1296. ; ;
  1297. ; Calls: ;
  1298. ; gjoin ;
  1299. ; gadd_free ;
  1300. ; ;
  1301. ; History: ;
  1302. ; ;
  1303. ; Mon Nov 17, 1986 11:41:49a -by- David N. Weise [davidw] ;
  1304. ; Added support for the free list of global partitions. ;
  1305. ; ;
  1306. ; Sun Nov 09, 1986 01:35:08p -by- David N. Weise [davidw] ;
  1307. ; Made the debugging version fill all free space with CCCC. ;
  1308. ; ;
  1309. ; Wed Sep 24, 1986 10:27:06p -by- David N. Weise [davidw] ;
  1310. ; Added this nifty comment block. ;
  1311. ;-----------------------------------------------------------------------;
  1312. cProc gmarkfree,<PUBLIC,NEAR>
  1313. cBegin nogen
  1314. call gadd_free
  1315. or esi,esi
  1316. jz short gmf_exit
  1317. ; Mark this block as free by clearing the owner field.
  1318. mov ds:[esi].pga_sig,GA_SIGNATURE
  1319. mov ds:[esi].pga_owner,di ; Mark as free
  1320. mov ds:[esi].pga_flags,0 ; For good measure.
  1321. ; Remember the handle value in DX, before setting to zero.
  1322. xor dx,dx
  1323. xchg ds:[esi].pga_handle,dx
  1324. ; Try to coalesce with next block, if it is free
  1325. push ds:[esi].pga_prev ; save previous block
  1326. mov esi,ds:[esi].pga_next ; ESI = next block
  1327. cmp ds:[esi].pga_owner,di ; Is it free?
  1328. jne short free2 ; No, continue
  1329. call gjoin ; Yes, coalesce with block we are freeing
  1330. free2:
  1331. pop esi ; ESI = previous block
  1332. cmp ds:[esi].pga_owner,di ; Is it free?
  1333. jne short free3 ; No, continue
  1334. mov esi,ds:[esi].pga_next ; Yes, coalesce with block we are freeing;
  1335. call gjoin
  1336. free3:
  1337. cmp ds:[esi].pga_owner,di ; Point to free block?
  1338. je short free4 ; Yes, done
  1339. mov esi,ds:[esi].pga_next ; No, leave ES pointing at free block
  1340. free4:
  1341. call gwin386discard
  1342. gmf_exit:
  1343. or dx,dx
  1344. ret
  1345. cEnd nogen
  1346. ;-----------------------------------------------------------------------;
  1347. ; gadd_free ;
  1348. ; ;
  1349. ; Links in the given partition into the global free list. ;
  1350. ; ;
  1351. ; Arguments: ;
  1352. ; EDX = the first free object before this one ;
  1353. ; 0 if unknown ;
  1354. ; odd if no free list update wanted ;
  1355. ; DS:DI = BurgerMaster ;
  1356. ; FS:ESI = free global object to add ;
  1357. ; ;
  1358. ; Returns: ;
  1359. ; ;
  1360. ; Error Returns: ;
  1361. ; ;
  1362. ; Registers Preserved: ;
  1363. ; all ;
  1364. ; ;
  1365. ; Registers Destroyed: ;
  1366. ; ;
  1367. ; Calls: ;
  1368. ; nothing ;
  1369. ; ;
  1370. ; History: ;
  1371. ; ;
  1372. ; Sun Nov 09, 1986 02:42:53p -by- David N. Weise [davidw] ;
  1373. ; Wrote it. ;
  1374. ;-----------------------------------------------------------------------;
  1375. cProc gadd_free,<PUBLIC,NEAR>
  1376. cBegin nogen
  1377. push eax
  1378. push edx
  1379. test dl,1
  1380. jnz short no_update_wanted
  1381. or esi,esi ; this happens with gmovebusy
  1382. jz short no_update_wanted
  1383. inc [di].gi_free_count
  1384. mov edx, esi
  1385. need_a_home_loop:
  1386. mov edx, ds:[edx].pga_prev
  1387. cmp ds:[edx].pga_owner, di ; Found a free block?
  1388. je short found_a_home
  1389. cmp ds:[edx].pga_prev, edx ; Sentinel?
  1390. jne short need_a_home_loop
  1391. found_a_home:
  1392. mov eax, ds:[edx].pga_freenext
  1393. mov ds:[esi].pga_freenext, eax
  1394. mov ds:[esi].pga_freeprev, edx
  1395. mov ds:[edx].pga_freenext, esi
  1396. mov ds:[eax].pga_freeprev, esi
  1397. if KDEBUG
  1398. call check_free_list
  1399. endif
  1400. gaf_exit:
  1401. no_update_wanted:
  1402. pop edx
  1403. pop eax
  1404. ret
  1405. cEnd nogen
  1406. ;-----------------------------------------------------------------------;
  1407. ; gdel_free ;
  1408. ; ;
  1409. ; Removes a partition from the global free list. ;
  1410. ; ;
  1411. ; Arguments: ;
  1412. ; DS:DI = BurgerMaster ;
  1413. ; FS:ESI = arena header of partition ;
  1414. ; ;
  1415. ; Returns: ;
  1416. ; ;
  1417. ; Error Returns: ;
  1418. ; ;
  1419. ; Registers Preserved: ;
  1420. ; All ;
  1421. ; ;
  1422. ; Registers Destroyed: ;
  1423. ; ;
  1424. ; Calls: ;
  1425. ; nothing ;
  1426. ; ;
  1427. ; History: ;
  1428. ; ;
  1429. ; Sun Nov 09, 1986 02:43:26p -by- David N. Weise [davidw] ;
  1430. ; Wrote it. ;
  1431. ;-----------------------------------------------------------------------;
  1432. cProc gdel_free,<PUBLIC,NEAR>
  1433. cBegin nogen
  1434. push edi
  1435. push esi
  1436. mov edi,ds:[esi].pga_freeprev
  1437. mov esi,ds:[esi].pga_freenext
  1438. mov ds:[edi].pga_freenext,esi
  1439. mov ds:[esi].pga_freeprev,edi
  1440. pop esi
  1441. pop edi
  1442. dec [di].gi_free_count
  1443. if KDEBUG
  1444. call check_free_list
  1445. endif
  1446. ret
  1447. cEnd nogen
  1448. if KDEBUG
  1449. ;-----------------------------------------------------------------------;
  1450. ; check_free_list ;
  1451. ; ;
  1452. ; Checks the global free list for consistency. ;
  1453. ; ;
  1454. ; Arguments: ;
  1455. ; none ;
  1456. ; ;
  1457. ; Returns: ;
  1458. ; ;
  1459. ; Error Returns: ;
  1460. ; ;
  1461. ; Registers Preserved: ;
  1462. ; All ;
  1463. ; ;
  1464. ; Registers Destroyed: ;
  1465. ; ;
  1466. ; Calls: ;
  1467. ; nothing ;
  1468. ; ;
  1469. ; History: ;
  1470. ; ;
  1471. ; Wed Oct 29, 1986 10:13:42a -by- David N. Weise [davidw] ;
  1472. ; Wrote it. ;
  1473. ;-----------------------------------------------------------------------;
  1474. cProc check_free_list,<PUBLIC,NEAR>
  1475. cBegin nogen
  1476. push eax
  1477. push ebx
  1478. push cx
  1479. push esi
  1480. push ds
  1481. SetKernelDS
  1482. cmp fCheckFree,0
  1483. jnz short cfl_outta_here
  1484. test Kernel_flags,kf_check_free
  1485. jnz short cfl_check_it_out
  1486. cfl_outta_here:
  1487. jmp all_done
  1488. cfl_check_it_out:
  1489. mov ds,pGlobalHeap
  1490. UnSetKernelDS
  1491. mov esi,[di].phi_first
  1492. mov cx,[di].gi_free_count
  1493. or cx,cx
  1494. jz all_done
  1495. mov eax, ds:[esi].pga_freenext
  1496. mov esi, eax
  1497. check_chain_loop:
  1498. mov ebx,ds:[esi].pga_freeprev
  1499. mov esi,ds:[esi].pga_freenext
  1500. cmp ds:[ebx].pga_freenext,eax
  1501. jz short prev_okay
  1502. prev_bad:
  1503. push esi
  1504. mov esi, eax
  1505. kerror 0FFh,<free_list: prev bad>,bx,si
  1506. mov eax, esi
  1507. pop esi
  1508. prev_okay:
  1509. cmp ds:[esi].pga_freeprev,eax
  1510. jnz short next_bad
  1511. mov ebx,esi
  1512. jmps next_okay
  1513. next_bad:
  1514. mov bx, ax
  1515. kerror 0FFh,<free_list: next bad>,bx,es
  1516. next_okay:
  1517. mov eax,esi
  1518. loop check_chain_loop
  1519. SetKernelDS
  1520. mov ds,pGlobalHeap
  1521. UnSetKernelDS
  1522. cmp [di].phi_last,eax
  1523. jz short all_done
  1524. mov bx, ax
  1525. kerror 0FFh,<free_list: count bad>,[di].phi_last,bx
  1526. all_done:
  1527. pop ds
  1528. pop esi
  1529. pop cx
  1530. pop ebx
  1531. pop eax
  1532. ret
  1533. cEnd nogen
  1534. endif
  1535. cProc ValidateFreeSpaces,<PUBLIC,FAR>
  1536. cBegin nogen
  1537. ret
  1538. cEnd nogen
  1539. sEnd CODE
  1540. end