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.

1580 lines
40 KiB

  1. TITLE LINTERF - Local memory allocator, interface procedures
  2. .xlist
  3. include tdb.inc
  4. include kernel.inc
  5. .list
  6. .errnz la_prev ; This code assumes la_prev = 0
  7. if KDEBUG
  8. CheckHeap MACRO n
  9. local a
  10. extrn CheckLocalHeap:NEAR
  11. cCall CheckLocalHeap
  12. or ax,ax
  13. jz a
  14. or ax,ERR_LMEM
  15. kerror <>,<&n: Invalid local heap>
  16. a:
  17. endm
  18. else
  19. CheckHeap MACRO n
  20. endm
  21. endif
  22. externW pLocalHeap
  23. externFP <GlobalHandle,GlobalReAlloc,GlobalSize,GlobalCompact,GlobalFlags>
  24. externFP <GlobalLock,GlobalUnlock>
  25. externFP <GlobalMasterHandle,GetCurrentTask>
  26. externFP FarValidatePointer
  27. externFP DibRealloc
  28. DataBegin
  29. externW curTDB
  30. ;externW MyCSDS
  31. if KDEBUG
  32. externW DebugOptions
  33. endif
  34. DataEnd
  35. sBegin CODE
  36. assumes CS,CODE
  37. assumes DS,NOTHING
  38. assumes ES,NOTHING
  39. externNP <halloc,lhfree,lhdref,hthread> ; LHANDLE.ASM
  40. externNP <ljoin,lrepsetup,lzero> ; LALLOC.ASM
  41. externNP <lalloc,lfree,lfreeadd,lfreedelete> ; LALLOC.ASM
  42. externNP <lcompact,lshrink> ; LCOMPACT.ASM
  43. if KDEBUG
  44. externNP <CheckLAllocBreak>
  45. endif ;KDEBUG
  46. ;-----------------------------------------------------------------------;
  47. ; lenter ;
  48. ; ;
  49. ; Enters a critical region for the local heap. ;
  50. ; ;
  51. ; Arguments: ;
  52. ; DS = automatic data segment containing local heap ;
  53. ; ;
  54. ; Returns: ;
  55. ; DS:DI = address of LocalInfo for local heap ;
  56. ; (li_lock field has been incremented) ;
  57. ; ;
  58. ; Error Returns: ;
  59. ; CX == 1 if heap is busy ;
  60. ; ;
  61. ; Registers Preserved: ;
  62. ; AX,BX,DX,SI,ES ;
  63. ; ;
  64. ; Registers Destroyed: ;
  65. ; CX ;
  66. ; ;
  67. ; Calls: ;
  68. ; nothing ;
  69. ; ;
  70. ; History: ;
  71. ; ;
  72. ; Sun Oct 13, 2086 09:27:27p -by- David N. Weise [davidw] ;
  73. ; Added this nifty comment block. ;
  74. ;-----------------------------------------------------------------------;
  75. cProc lenter,<PUBLIC,NEAR>
  76. cBegin nogen
  77. mov di,pLocalHeap
  78. mov cx,1
  79. xchg [di].li_lock,cx
  80. jcxz enter1
  81. ; Should really do a WaitEvent
  82. if KDEBUG
  83. xor bx,bx
  84. kerror ERR_LMEMCRIT,<lenter: local heap is busy>,bx,cx
  85. endif
  86. enter1: ret
  87. cEnd nogen
  88. ;-----------------------------------------------------------------------;
  89. ; lleave ;
  90. ; ;
  91. ; Leaves a critical region for the local heap. ;
  92. ; ;
  93. ; Arguments: ;
  94. ; DS = automatic data segment containing local heap ;
  95. ; ;
  96. ; Returns: ;
  97. ; DS:DI = address of LocalInfo for local heap ;
  98. ; (li_lock field has been cleared) ;
  99. ; ;
  100. ; Error Returns: ;
  101. ; ;
  102. ; Registers Preserved: ;
  103. ; AX,BX,DX,SI,ES ;
  104. ; ;
  105. ; Registers Destroyed: ;
  106. ; CX ;
  107. ; ;
  108. ; Calls: ;
  109. ; nothing ;
  110. ; ;
  111. ; History: ;
  112. ; ;
  113. ; Sun Oct 13, 2086 09:30:01p -by- David N. Weise [davidw] ;
  114. ; Added this nifty comment block. ;
  115. ;-----------------------------------------------------------------------;
  116. cProc lleave,<PUBLIC,NEAR>
  117. cBegin nogen
  118. mov di,pLocalHeap
  119. xor cx,cx
  120. xchg ds:[di].li_lock,cx
  121. jcxz leave1
  122. ret
  123. leave1:
  124. ; Should really do a PostEvent
  125. if KDEBUG
  126. kerror ERR_LMEMCRIT,<lleave: local heap was not busy>
  127. endif
  128. cEnd nogen
  129. ;-----------------------------------------------------------------------;
  130. ; lhexpand ;
  131. ; ;
  132. ; Expands a local handle table. ;
  133. ; ;
  134. ; Arguments: ;
  135. ; CX = #handle entries to allocate ;
  136. ; DS:DI = local info structure ;
  137. ; ;
  138. ; Returns: ;
  139. ; AX = address of handle table block of requested size ;
  140. ; ;
  141. ; Error Returns: ;
  142. ; ;
  143. ; Registers Preserved: ;
  144. ; ;
  145. ; Registers Destroyed: ;
  146. ; BX,CX,DX,ES ;
  147. ; ;
  148. ; Calls: ;
  149. ; lalloc ;
  150. ; hthread ;
  151. ; ;
  152. ; History: ;
  153. ; ;
  154. ; Tue Oct 14, 1986 01:48:21p -by- David N. Weise [davidw] ;
  155. ; Added this nifty comment block. ;
  156. ;-----------------------------------------------------------------------;
  157. cProc lhexpand,<PUBLIC,NEAR>
  158. cBegin nogen
  159. xor ax,ax ; Allocate fixed local block
  160. mov bx,cx
  161. inc bx ; plus 1 for word at beginning & end
  162. shl bx,1
  163. shl bx,1
  164. errnz <4-SIZE LocalHandleEntry>
  165. push cx
  166. call lalloc
  167. pop cx
  168. or ax,ax
  169. jz lhfail
  170. mov bx,ax
  171. xchg [di].hi_htable,bx
  172. push di ; Save DI
  173. mov di,ax
  174. mov ds:[di],cx
  175. inc di
  176. inc di
  177. call hthread
  178. mov ds:[di],bx ; Store pointer to next block
  179. pop di ; Restore DI
  180. lhfail: mov cx,ax
  181. ret
  182. cEnd nogen
  183. ;-----------------------------------------------------------------------;
  184. ; lalign ;
  185. ; ;
  186. ; Aligns the size request for a local item to a multiple of 4 bytes. ;
  187. ; ;
  188. ; Arguments: ;
  189. ; CF = 0 ;
  190. ; BX = #bytes ;
  191. ; CF = 1 get max amount ;
  192. ; ;
  193. ; Returns: ;
  194. ; DX = #bytes aligned to next higher multiple of 4 ;
  195. ; ;
  196. ; Error Returns: ;
  197. ; ;
  198. ; Registers Preserved: ;
  199. ; ;
  200. ; Registers Destroyed: ;
  201. ; ;
  202. ; Calls: ;
  203. ; nothing ;
  204. ; ;
  205. ; History: ;
  206. ; ;
  207. ; Tue March 10, 1987 -by- Bob Gunderson [bobgu] ;
  208. ; To accomidate free list, must impose a minimum block size to prevent ;
  209. ; allocating a block on top of the extended header of previous block. ;
  210. ; ;
  211. ; Tue Oct 14, 1986 01:56:42p -by- David N. Weise [davidw] ;
  212. ; Added this nifty comment block. ;
  213. ;-----------------------------------------------------------------------;
  214. cProc lalign,<PUBLIC,NEAR>
  215. cBegin nogen
  216. jnc align0
  217. mov bx,LA_MASK
  218. align0: cmp bx,SIZE LocalArenaFree
  219. jae align2
  220. mov bx,SIZE LocalArenaFree ; Must impose a minimum size
  221. align2: lea dx,[bx+LA_ALIGN]
  222. and dl,LA_MASK
  223. cmp dx,bx ; Test for overflow
  224. jae align1 ; No, continue
  225. mov dx,LA_MASK ; Yes, return largest possible size
  226. align1: ret
  227. cEnd nogen
  228. ;-----------------------------------------------------------------------;
  229. ; ldref ;
  230. ; ;
  231. ; Dereferences a local handle. ;
  232. ; ;
  233. ; Arguments: ;
  234. ; SI = handle ;
  235. ; ;
  236. ; Returns: ;
  237. ; AX = address of client data ;
  238. ; BX = address of arena header ;
  239. ; CH = lock count or zero for fixed objects ;
  240. ; SI = handle table entry address or zero for fixed objects ;
  241. ; ZF = 1 if NULL handle passed in ;
  242. ; ;
  243. ; Error Returns: ;
  244. ; ;
  245. ; Registers Preserved: ;
  246. ; ;
  247. ; Registers Destroyed: ;
  248. ; CL ;
  249. ; ;
  250. ; Calls: ;
  251. ; lhdref ;
  252. ; ;
  253. ; History: ;
  254. ; ;
  255. ; Tue Oct 14, 1986 01:58:58p -by- David N. Weise [davidw] ;
  256. ; Added this nifty comment block. ;
  257. ;-----------------------------------------------------------------------;
  258. cProc ldref,<PUBLIC,NEAR>
  259. cBegin nogen
  260. xor cx,cx ; Zero lock count
  261. mov ax,si ; Return handle if fixed object
  262. test al,LA_MOVEABLE ; Is it moveable?
  263. jnz dref3 ; Yes, go dereference handle
  264. xor si,si ; Set SI to zero for fixed objects
  265. or ax,ax ; No, were we passed NULL?
  266. jz dref2 ; Yes, then all done
  267. dref1: mov bx,ax ; No, return BX pointing
  268. and bl,LA_MASK ; ...to arena header
  269. sub bx,la_fixedsize ; Leaving ZF = 0
  270. dref2: ret
  271. dref3: call lhdref ; Get true address in AX
  272. ; and lock count in CH
  273. ife KDEBUG
  274. jz done ; Compute arena header if valid true address
  275. mov bx,ax ; See if arena header points to
  276. sub bx,SIZE LocalArena
  277. done: ret ; No, return with ZF = 1
  278. else
  279. test cl,LHE_DISCARDED ; Discarded?
  280. jnz dref5 ; Yes, all done
  281. or ax,ax ; Is there a true address?
  282. jz dref4 ; No, then must be error
  283. mov bx,ax ; See if arena header points to
  284. sub bx,SIZE LocalArena
  285. cmp [bx].la_handle,si ; handle table entry?
  286. je dref5 ; Yes, continue
  287. dref4: xor bx,bx
  288. kerror ERR_LMEMHANDLE,<LDREF: Invalid local handle>,bx,si
  289. xor ax,ax
  290. dref5: or ax,ax
  291. ret
  292. endif
  293. cEnd nogen
  294. ;-----------------------------------------------------------------------;
  295. ; lnotify ;
  296. ; ;
  297. ; Calls the local heap's notify proc (if any). ;
  298. ; ;
  299. ; Arguments: ;
  300. ; AL = message code ;
  301. ; BX = handle or largest free block ;
  302. ; CX = optional argument ;
  303. ; ;
  304. ; Returns: ;
  305. ; AX = return value from notify proc or AL ;
  306. ; ZF = 1 if AX = 0 ;
  307. ; ;
  308. ; Error Returns: ;
  309. ; ;
  310. ; Registers Preserved: ;
  311. ; ;
  312. ; Registers Destroyed: ;
  313. ; BX,CX,DX,ES ;
  314. ; ;
  315. ; Calls: ;
  316. ; ;
  317. ; History: ;
  318. ; ;
  319. ; Tue Oct 14, 1986 02:03:14p -by- David N. Weise [davidw] ;
  320. ; Added this nifty comment block. ;
  321. ;-----------------------------------------------------------------------;
  322. cProc lnotify,<PUBLIC,NEAR>
  323. cBegin nogen
  324. cmp word ptr [di+2].li_notify,0
  325. je notify1
  326. xor ah,ah
  327. cCall [di].li_notify,<ax,bx,cx>
  328. notify1:
  329. or ax,ax
  330. ret
  331. cEnd nogen
  332. ; The remainder of this file implements the exported interface to the
  333. ; local memory manager. A summary follows:
  334. ;
  335. ; HANDLE far PASCAL LocalAlloc( WORD, WORD );
  336. ; HANDLE far PASCAL LocalReAlloc( HANDLE, WORD, WORD );
  337. ; HANDLE far PASCAL LocalFree( HANDLE );
  338. ; WORD far PASCAL LocalSize( HANDLE );
  339. ; char * far PASCAL LocalLock( HANDLE );
  340. ; BOOL far PASCAL LocalUnlock( HANDLE );
  341. ; WORD far PASCAL LocalCompact( WORD );
  342. ; WORD far PASCAL LocalShrink( HANDLE , WORD );
  343. ; FARPROC far PASCAL LocalNotify( FARPROC );
  344. ; #define LocalDiscard( h ) LocalReAlloc( h, 0, LMEM_MOVEABLE )
  345. ; BOOL far PASCAL LocalInit( char *, char * );
  346. ;
  347. ; extern WORD * PASCAL pLocalHeap;
  348. ;
  349. ; #define dummy 0
  350. ; #define LocalFreeze( dummy ) ( *(pLocalHeap+1) += 1 )
  351. ; #define LocalThaw( dummy ) ( *(pLocalHeap+1) -= 1 )
  352. ;
  353. cProc ILocalAlloc,<PUBLIC,FAR>,<si,di>
  354. parmW flags
  355. parmW nbytes
  356. cBegin
  357. WOWTrace "LocalAlloc(#AX,#BX)",<<ax,flags>,<bx,nbytes>>
  358. CheckHeap LocalAlloc
  359. call lenter ; About to modify memory arena
  360. jcxz la_ok
  361. xor ax, ax
  362. jmp la_crit
  363. la_ok:
  364. mov ax,flags ; Allocate space for object
  365. test al,LA_NOCOMPACT
  366. jz all0
  367. inc [di].hi_freeze
  368. all0: mov bx,nbytes
  369. or bx,bx ; Zero length?
  370. jnz alloc0 ; No, continue
  371. and ax,LA_MOVEABLE ; Yes, moveable?
  372. jz alloc1 ; No, return error
  373. call halloc ; Yes, allocate handle
  374. or ax,ax ; failure??
  375. jz alloc1 ; yep... return a NULL
  376. xor byte ptr [bx].lhe_address,LA_MOVEABLE ; and zero address field
  377. or byte ptr [bx].lhe_flags,LHE_DISCARDED ; and mark as discarded
  378. jmps alloc1 ; all done
  379. alloc0: test al,LA_MOVEABLE ; Is this a moveable object?
  380. jz dont_need_handle
  381. push ax
  382. push bx
  383. call halloc ; Allocate handle first.
  384. or ax,ax
  385. jnz all2 ; error?
  386. pop bx ; yes, DON'T destroy the NULL in AX
  387. pop bx
  388. jmps alloc1
  389. all2:
  390. pop bx
  391. pop ax
  392. ; pop bx
  393. ; pop ax
  394. ; jcxz alloc1
  395. push cx ; this is handle
  396. call lalloc
  397. pop si ; get handle in index register
  398. jnz got_space
  399. call lhfree ; free the allocated handle
  400. jmps alloc1
  401. got_space:
  402. mov [si].lhe_address,ax ; Store address away.
  403. mov bx,ax ; Store back link to handle in header
  404. mov [bx-SIZE LocalArena].la_handle,si ; Mark as moveable block
  405. or byte ptr [bx-SIZE LocalArena].la_prev,LA_MOVEABLE
  406. mov ax,si ; return the handle
  407. and dh,LHE_DISCARDABLE ; Discardable object?
  408. jz alloc1 ; No, continue
  409. mov [si].lhe_flags,dh ; Yes, save discard level in handle
  410. jmps alloc1 ; table entry
  411. dont_need_handle:
  412. call lalloc
  413. alloc1: test byte ptr flags,LA_NOCOMPACT
  414. jz all1
  415. dec [di].hi_freeze
  416. all1: call lleave ; Arena is consistent now
  417. la_crit:
  418. ifdef WOW
  419. ; We don't want this debug spew
  420. else
  421. or ax,ax
  422. jnz @F
  423. KernelLogError DBF_WARNING,ERR_LALLOC,"LocalAlloc failed" ; LocalAlloc failure
  424. xor ax, ax ; preserve the return value
  425. @@:
  426. endif
  427. mov cx,ax ; Let caller do jcxz to test failure
  428. WOWTrace "LocalAlloc: #AX"
  429. cEnd
  430. cProc ILocalReAlloc,<PUBLIC,FAR>,<si,di>
  431. parmW h
  432. parmW nbytes
  433. parmW rflags
  434. cBegin
  435. WOWTrace "LocalReAlloc(#AX,#BX,#CX)",<<ax,h>,<bx,nbytes>,<cx,rflags>>
  436. CheckHeap LocalReAlloc
  437. call lenter ; About to modify memory arena
  438. jcxz lr_ok
  439. xor ax, ax
  440. jmp lr_crit
  441. lr_ok:
  442. test byte ptr rflags,LA_NOCOMPACT
  443. jz rel0
  444. inc [di].hi_freeze
  445. rel0:
  446. mov si,h ; Dereference handle
  447. call ldref
  448. jz racreate ; If zero handle, check for re-creation.
  449. test byte ptr rflags,LA_MODIFY ; Want to modify handle table flags
  450. jnz ramodify ; Yes, go do it
  451. mov si,bx ; SI = arena header
  452. mov bx,ax ; Compute address of new next header
  453. mov dx,nbytes ; assuming there is room.
  454. cmp dx,SIZE LocalArenaFree ; Minimum size must be large enough
  455. jae @F ; to a hold free header.
  456. mov dx,SIZE LocalArenaFree
  457. @@: add bx,dx
  458. call lalign
  459. mov bx,[si].la_next ; Get address of current next header
  460. cmp nbytes,0 ; Are we reallocing to zero length?
  461. jne raokay ; No, continue
  462. jcxz radiscard ; Yes, discard if not locked
  463. rafail:
  464. ifdef WOW
  465. ; We don't want this debug spew
  466. else
  467. KernelLogError DBF_WARNING,ERR_LREALLOC,"LocalReAlloc failed"
  468. endif
  469. xor ax,ax
  470. jmp raexit
  471. radiscard:
  472. ; Here to discard object, when reallocating to zero size. This
  473. ; feature is only enabled if the caller passes the moveable flag
  474. test byte ptr rflags,LA_MOVEABLE ; Did they want to discard?
  475. jz rafail ; No, then return failure.
  476. mov al,LN_DISCARD ; AL = discard message code
  477. xor cx,cx ; CX = disc level of 0 (means realloc)
  478. mov bx,h ; BX = handle
  479. call lnotify ; See if okay to discard
  480. jz rafail ; No, do nothing
  481. xor ax,ax ; Yes, free client data
  482. mov bx,si
  483. call lfree
  484. jz rax ; Return NULL if freed a fixed block
  485. mov [si].lhe_address,ax ; No, zero addr in handle table entry
  486. or [si].lhe_flags,LHE_DISCARDED ; and mark as discarded
  487. jmps rasame ; Return original handle, except
  488. ; LocalLock will now return null.
  489. ramodify:
  490. mov ax,rflags ; Get new flags
  491. or si,si ; Moveable object?
  492. jz rasame ; No, all done
  493. and [si].lhe_flags,not LHE_USERFLAGS ; Clear old flags
  494. and ah,LHE_USERFLAGS; Get new flags
  495. or [si].lhe_flags,ah ; Store new flags in handle table entry
  496. jmps rasame
  497. racreate:
  498. test cl,LHE_DISCARDED ; Is this a discarded handle?
  499. jz rasame ; No, return original value
  500. mov bx,nbytes ; BX = new requested size
  501. push si ; save handle
  502. mov ax,LA_MOVEABLE ; Reallocating a moveable object
  503. or ax,rflags ; ...plus any flags from the caller
  504. call lalloc ; Allocate a new block
  505. pop si ; restore existing handle
  506. jz rafail
  507. xor [si].lhe_flags,LHE_DISCARDED ; and mark as not discarded
  508. jmp ram2
  509. raokay:
  510. ; Here if not trying to realloc this block to zero
  511. ; SI = arena header of current block
  512. ; AX = client address of current block
  513. ; BX = arena header of next block
  514. ; CH = lock count of current block
  515. ; DX = new next block, based on new requested size
  516. cmp dx,bx ; Are we growing or shrinking?
  517. ja ragrow ; We are growing
  518. rashrink: ; We are shrinking
  519. ; Here to shrink a block
  520. ; SI = arena header of current block
  521. ; BX = arena header of next block
  522. ; DX = new next block, based on new requested size
  523. push si
  524. mov si,dx ; SI = new next block
  525. add dx,LA_MINBLOCKSIZE ; Test for small shrinkage
  526. jnc @F ; No overflow
  527. pop bx ; Overflowed, obviously no room!
  528. jmp rasame ; Clear stack and return same handle
  529. @@: cmp dx,bx ; Is there room from for free block?
  530. pop bx ; BX = current block
  531. jae rasame ; No, then no change to make
  532. ; Splice extra free space into arena
  533. mov cx,si ; [si].la_next = [bx].la_next
  534. xchg [bx].la_next,cx ; [bx].la_next = si
  535. mov [si].la_prev,bx ; [si].la_prev = bx
  536. xchg si,cx
  537. and [si].la_prev,LA_ALIGN
  538. jz splice1 ; If free then coelesce
  539. inc [di].hi_count ; No, adding new arena entry
  540. jmps splice2
  541. splice1:
  542. ; next block is free, must make the new block a larger free block
  543. ; first remove the current free block [SI] from the free list
  544. xchg bx,si
  545. call lfreedelete
  546. xchg bx,si
  547. mov si,[si].la_next
  548. and [si].la_prev,LA_ALIGN
  549. splice2:
  550. or [si].la_prev,cx ; [[si].la_next].la_prev = si
  551. xchg si,cx
  552. mov [si].la_next,cx
  553. mov bx,si ; BX = new block
  554. xor si,si ; don't know where to insert
  555. call lfreeadd ; add to free list
  556. rasame:
  557. mov ax,h ; Return the same handle
  558. rax: jmps raexit ; All done
  559. ; Here to try to grow the current block
  560. ; AX = client address of current block
  561. ; SI = arena header of current block
  562. ; BX = arena header of next block
  563. ; DX = new next block, based on new requested size
  564. ragrow:
  565. if KDEBUG
  566. call CheckLAllocBreak
  567. jc rafail1
  568. endif
  569. test byte ptr [bx].la_prev,LA_BUSY ; Is next block free?
  570. jnz ramove ; No, try to move the current block
  571. cmp dx,[bx].la_next ; Yes, is free block big enough?
  572. ja ramove ; No, try to move the current block
  573. mov cx,bx ; Yes, save free block address in CX
  574. call ljoin ; and attach to end of current block
  575. test rflags,LA_ZEROINIT ; Zero fill extension?
  576. jz ranz ; No, continue
  577. call lzero ; Yes, zero fill
  578. ranz:
  579. jmp rashrink ; Now shrink block to correct size
  580. ; Here to try to move the current block
  581. ; AX = client address of current block
  582. ; SI = arena header of current block
  583. ; CH = lock count of current block
  584. ramove:
  585. mov dx,rflags ; get the passed in flags
  586. mov bx,LA_MOVEABLE ; Determine if okay to move this guy
  587. jcxz ramove1 ; Continue if this handle not locked
  588. test dx,bx ; Locked. Did they say move anyway?
  589. jnz ramove1 ; Yes, go do it
  590. rafail1:jmp rafail
  591. ramove1:
  592. or dx,bx ; make sure moveable bit set
  593. test h,bx ; Is it a moveable handle?
  594. jnz ram1 ; Yes, okay to move
  595. test rflags,bx ; No, did they say it's okay to move?
  596. jz rafail1 ; No, then fail
  597. xor dx,bx ; turn off moveable bit
  598. ram1:
  599. ; We do this because the lalloc can move the old block to a
  600. ; block that is larger than the requested new block. This can
  601. ; happen if we LocalCompact durring the lalloc call. (bobgu 8/27/87)
  602. mov bx,[si].la_next
  603. sub bx,ax ; # client bytes in current block
  604. push bx ; save it for later
  605. mov ax,dx ; AX = allocation flags
  606. mov bx,nbytes ; BX = new requested size
  607. call lalloc ; Allocate a new block
  608. pop cx ; CX = client size of old block
  609. jz rafail1
  610. push cx ; save it away again
  611. push ax ; Call notify proc
  612. mov cx,ax ; with new location
  613. mov bx,h ; handle
  614. mov al,LN_MOVE
  615. call lnotify ; Notify client of new location
  616. mov si,h
  617. call ldref ; BX = old arena header address
  618. mov si,ax ; SI = old client address
  619. pop ax ; AX = new client address
  620. pop cx ; get back size of old client
  621. ; mov cx,[bx].la_next ; Compute length of old client data
  622. ; sub cx,si
  623. call lrepsetup ; Setup for copy of words
  624. push di
  625. mov di,ax ; DI = new client data address
  626. rep movsw ; Copy old client data to new area
  627. pop di ; Restore DI
  628. call lfree ; Free old block
  629. jz raexit
  630. ram2:
  631. mov [si].lhe_address,ax ; Set new client data address
  632. xchg ax,si ; Return original handle
  633. ; Set back link to handle in new block
  634. or byte ptr [si-SIZE LocalArena].la_prev,LA_MOVEABLE
  635. mov [si-SIZE LocalArena].la_handle,ax
  636. raexit:
  637. test byte ptr rflags,LA_NOCOMPACT
  638. jz rel1
  639. dec [di].hi_freeze
  640. rel1:
  641. call lleave ; Arena is consistent now
  642. lr_crit:
  643. mov cx,ax ; Let caller do jcxz to test failure
  644. WOWTrace "LocalReAlloc: #AX"
  645. cEnd
  646. cProc ILocalFree,<PUBLIC,FAR>,<si,di>
  647. parmW h
  648. cBegin
  649. WOWTrace "LocalFree(#AX)",<<ax,h>>
  650. call lenter ; About to modify memory arena
  651. jcxz lf_ok
  652. xor ax, ax
  653. jmp lf_crit
  654. lf_ok:
  655. CheckHeap LocalFree
  656. mov si,h ; Dereference handle
  657. call ldref
  658. jz free1 ; Free handle if object discarded
  659. if KDEBUG
  660. push ds
  661. SetKernelDS
  662. mov ds,curTDB
  663. assumes ds, nothing
  664. cmp ds:[TDB_ExpWinVer],201h
  665. pop ds
  666. jb dont_do_error_checking
  667. or ch,ch ; No, is the handle locked?
  668. jz freeo ; Yes, then don't free
  669. xor bx,bx
  670. kerror ERR_LMEMUNLOCK,<LocalFree: freeing locked object>,bx,h
  671. mov si,h ; Dereference handle again
  672. call ldref
  673. freeo:
  674. dont_do_error_checking:
  675. endif
  676. call lfree ; No, free the object
  677. free1: call lhfree ; and any handle
  678. freex: call lleave ; Arena is consistent now
  679. lf_crit:
  680. WOWTrace "LocalFree: #AX"
  681. cEnd
  682. cProc ILocalSize,<PUBLIC,FAR>
  683. ; parmW h
  684. cBegin nogen
  685. ; CheckHeap LocalSize
  686. push si
  687. mov si,sp
  688. mov si,ss:[si+6] ; Dereference handle
  689. call ldref ; into BX
  690. jz size1 ; Done if AX = zero
  691. sub ax,[bx].la_next ; Otherwise size =
  692. neg ax ; - (client address - next block address)
  693. size1: mov cx,ax ; Let caller do jcxz to test failure
  694. pop si
  695. ret 2
  696. cEnd nogen
  697. cProc ILocalFlags,<PUBLIC,FAR>
  698. ; parmW h
  699. cBegin nogen
  700. ; CheckHeap LocalFlags
  701. push si
  702. mov si,sp
  703. mov si,ss:[si+6] ; Dereference handle
  704. call ldref ; into BX
  705. mov cx,si
  706. jcxz flags1 ; Done if not moveable
  707. mov cx,word ptr [si].lhe_flags ; Return flags and lock count
  708. flags1:
  709. xchg cl,ch ; Return lock count in low half
  710. mov ax,cx ; Let caller do jcxz to test failure
  711. pop si
  712. ret 2
  713. cEnd nogen
  714. if KDEBUG
  715. cProc ILocalLock,<PUBLIC,FAR>,<si>
  716. parmW h
  717. cBegin
  718. WOWTrace "LocalLock(#AX)",<<ax,h>>
  719. ; CheckHeap LocalLock
  720. mov si,h
  721. call ldref ; SI = handle table entry
  722. jz lock2 ; Done if invalid handle or discarded
  723. or si,si
  724. jz lock2 ; or if not moveable
  725. inc [si].lhe_count ; Increment usage count
  726. jnz lock1
  727. xor cx,cx
  728. kerror ERR_LMEMLOCK,<LocalLock: Object usage count overflow>,cx,h
  729. dec [si].lhe_count ; Keep pinned at max value
  730. lock1: mov ax,[si].lhe_address ; Return true address in AX
  731. lock2:
  732. or ax, ax
  733. jnz @F
  734. KernelLogError DBF_WARNING,ERR_LLOCK,"LocalLock failed"
  735. xor ax,ax ; Get back the NULL value in ax
  736. @@: mov cx,ax ; Let caller do jcxz to test failure
  737. WOWTrace "LocalLock: #AX"
  738. cEnd
  739. else
  740. cProc ILocalLock,<PUBLIC,FAR>
  741. ; parmW h
  742. cBegin nogen
  743. mov bx,sp ; Get handle parameter from stack
  744. mov bx,SS:[bx+4]
  745. mov ax,bx ; Return in AX
  746. test bl,LA_MOVEABLE ; Test for moveable (also null)
  747. jz lock2 ; Return if not moveable or null
  748. test [bx].lhe_flags,LHE_DISCARDED ; Return zero if discarded
  749. jnz lock1
  750. inc [bx].lhe_count ; Increment usage count
  751. jz lock3 ; Special case if overflow
  752. lock1:
  753. mov ax,[bx].lhe_address ; Return true address in AX or zero
  754. lock2: mov cx,ax ; Let caller do jcxz to test failure
  755. ret 2
  756. lock3:
  757. dec [bx].lhe_count ; Ooops, keep pinned at max value
  758. jmp lock1
  759. cEnd nogen
  760. endif
  761. if KDEBUG
  762. cProc ILocalUnlock,<PUBLIC,FAR>,<si>
  763. parmW h
  764. cBegin
  765. WOWTrace "LocalUnlock(#AX)",<<ax,h>>
  766. ; CheckHeap LocalUnlock
  767. mov si,h
  768. call ldref ; SI = handle table entry
  769. jz unlock1 ; Done if invalid handle or discarded
  770. xor ax,ax
  771. or si,si
  772. jz unlock1 ; or if not moveable
  773. or ch, ch
  774. jz unlockerr
  775. dec ch ; Decrement usage count
  776. cmp ch,0FFh-1 ; 0 -> ff, ff -> fe
  777. jae unlock1 ; Return if pinned or already unlocked
  778. mov [si].lhe_count,ch
  779. ; mov ax,bx
  780. mov al,ch
  781. cbw
  782. jmps unlock1
  783. unlockerr:
  784. xor cx,cx
  785. kerror ERR_LMEMUNLOCK,<LocalUnlock: Object usage count underflow>,cx,h
  786. xor ax,ax
  787. unlock1:
  788. mov cx,ax ; Let caller do jcxz to test failure
  789. WOWTrace "LocalUnlock: #AX"
  790. cEnd
  791. else
  792. cProc ILocalUnlock,<PUBLIC,FAR>
  793. ; parmW h
  794. cBegin nogen
  795. mov bx,sp ; Get handle parameter from stack
  796. mov bx,SS:[bx+4]
  797. xor ax,ax
  798. test bl,LA_MOVEABLE ; Test for moveable (also null)
  799. jz unlock1 ; Return if not moveable or null
  800. mov cx,word ptr [bx].lhe_flags
  801. errnz <2-lhe_flags>
  802. errnz <3-lhe_count>
  803. and cl,LHE_DISCARDED
  804. jnz unlock1 ; Return if discarded
  805. dec ch ; Decrement usage count
  806. cmp ch,0FFh-1 ; 0 -> ff, ff -> fe
  807. jae unlock1 ; Return if pinned or already unlocked
  808. mov [bx].lhe_count,ch
  809. ; mov ax,bx
  810. mov al,ch
  811. cbw
  812. unlock1:
  813. mov cx,ax ; Let caller do jcxz to test failure
  814. ret 2
  815. cEnd nogen
  816. endif
  817. cProc LocalHandle,<PUBLIC,FAR>
  818. ; parmW h
  819. cBegin nogen
  820. mov bx,sp
  821. mov bx,SS:[bx+4]
  822. test bl,LA_MOVEABLE
  823. jz lh1
  824. mov ax,bx
  825. mov bx,[bx-SIZE LocalArena].la_handle
  826. cmp [bx].lhe_address,ax
  827. je lh1
  828. xor bx,bx
  829. lh1:
  830. mov ax,bx
  831. ret 2
  832. cEnd nogen
  833. cProc LocalCompact,<PUBLIC,FAR>,<si,di>
  834. parmW minBytes
  835. cBegin
  836. CheckHeap LocalCompact
  837. call lenter ; About to modify memory arena
  838. jcxz lc_ok
  839. xor ax, ax
  840. jmp lc_crit
  841. lc_ok:
  842. mov bx,minBytes
  843. clc
  844. call lalign
  845. call lcompact
  846. or ax,ax
  847. jz compact1
  848. sub ax,SIZE LocalArena ; Reduce available size by header size
  849. compact1:
  850. call lleave ; Arena is consistent now
  851. lc_crit:
  852. cEnd
  853. cProc LocalShrink,<PUBLIC,FAR>,<si,di>
  854. parmW hseg
  855. parmW wsize
  856. cBegin
  857. mov ax,hseg
  858. or ax,ax ; use heap in current DS ?
  859. jz ls_useds ; yes
  860. ; Use the segment handle passed
  861. push ax
  862. call GlobalHandle
  863. or ax,ax ; valid handle ?
  864. jz ls_errexit ; no....
  865. mov ds,dx ; set the proper DS
  866. ls_useds:
  867. ; check the heap and lock it
  868. CheckHeap LocalShrink
  869. call lenter ; About to modify memory arena
  870. jcxz ls_ok
  871. xor ax, ax
  872. jmp short ls_crit
  873. ls_ok:
  874. mov bx,wsize ; get requested min size
  875. call lshrink ; Let's get small
  876. ; AX = new local heap size
  877. call lleave ; Arena is consistent now
  878. ls_crit:
  879. ls_errexit:
  880. cEnd
  881. cProc LocalNotifyDefault,<PUBLIC,FAR>,<si,di>
  882. parmW msg
  883. parmW handle ; or largest free block
  884. parmW arg1
  885. cBegin
  886. mov ax,msg
  887. or ax,ax
  888. jnz dlnexit1
  889. cCall GlobalHandle,<ds>
  890. or ax,ax
  891. jz dlnexit1
  892. ; Fix for FORMBASE who uses a fixed
  893. ; segment for a local heap. This blows
  894. ; up if we cause the calling segment
  895. ; to be discarded since the DS saved by
  896. ; Local???? is a fixed segment which
  897. ; SearchStack can't handle. Confused?
  898. ; This was not a problem in 2.x because
  899. ; 2.x failed to grow a fixed object.
  900. ; Using a fixed segment for a local heap
  901. ; is not valid and this is really a problem
  902. ; with FORMBASE.
  903. mov si,ax
  904. cCall GlobalFlags,<si> ; Get flags
  905. xchg ah, al
  906. push ax
  907. cCall GlobalSize,<si>
  908. sub ax, handle ; Temorarily subtract out largest free
  909. pop bx ; Get flags in BX
  910. xor cx,cx
  911. add ax,arg1
  912. adc dx,cx ; Fail if DS attempts to grow
  913. jnz dln_too_large ; beyond 64k.
  914. add ax,18h ; since li_extra isn't guaranteed
  915. adc dx,cx
  916. jnz dln_too_large
  917. add ax,[di].li_extra
  918. adc dx,cx ; Fail if DS attempts to grow
  919. jnz @F ; beyond 64k.
  920. add ax, handle ; add back largest free
  921. adc dx, cx
  922. jnz @F
  923. cmp ax,0FFF0h
  924. jbe dln0
  925. @@: mov ax,0FFF0h
  926. xor dx,dx
  927. jmps dln0
  928. dln_too_large:
  929. xor ax,ax
  930. dlnexit1:
  931. jmp dlnexit
  932. dln0:
  933. test si,GA_FIXED ; Is DS fixed?
  934. jnz dln1 ; Yes, must grow in place
  935. cmp bh,1 ; No, is lock count 1?
  936. jne dln1 ; No must grow in place if locked
  937. or cl,GA_MOVEABLE ; Yes, okay to move even though locked
  938. dln1:
  939. push bx
  940. grow_DS:
  941. cCall GlobalReAlloc,<si,dxax,cx>
  942. pop bx
  943. jcxz dlnexit
  944. push bx
  945. cCall GlobalSize,<ax>
  946. or dx,dx ; Did we get rounded up >= 64K?
  947. jz @F ; No, OK
  948. mov ax,0FFFFh ; This only happens under 386pmode
  949. @@:
  950. mov bx,ax
  951. sub bx,la_freefixedsize
  952. and bl,LA_MASK
  953. mov di,ds:[pLocalHeap]
  954. mov si,[di].hi_last
  955. mov [bx].la_next,bx
  956. mov [bx].la_prev,si
  957. or byte ptr [bx].la_prev,LA_BUSY
  958. mov [si].la_next,bx
  959. ; Maintain the free list.
  960. mov ax,[si].la_free_prev
  961. mov [bx].la_free_prev,ax
  962. mov [bx].la_free_next,bx
  963. mov [bx].la_size,WORD PTR la_freefixedsize
  964. push si
  965. mov si,ax
  966. mov [si].la_free_next,bx
  967. pop si
  968. mov [di].hi_last,bx
  969. inc [di].hi_count
  970. mov bx,si
  971. call lfree
  972. ; Don't do this... (bobgu 8/4/87)
  973. ; stc
  974. ; call lalign
  975. ; call lcompact
  976. mov ax,1
  977. pop bx
  978. mov ax,1
  979. dlnexit:
  980. cEnd
  981. cProc LocalNotifyDib,<PUBLIC,FAR>,<si,di>
  982. parmW msg
  983. parmW handle ; or largest free block
  984. parmW arg1
  985. cBegin
  986. mov ax,msg
  987. or ax,ax
  988. jnz dlnexit1dib
  989. cCall GlobalHandle,<ds>
  990. or ax,ax
  991. jz dlnexit1dib
  992. ; Fix for FORMBASE who uses a fixed
  993. ; segment for a local heap. This blows
  994. ; up if we cause the calling segment
  995. ; to be discarded since the DS saved by
  996. ; Local???? is a fixed segment which
  997. ; SearchStack can't handle. Confused?
  998. ; This was not a problem in 2.x because
  999. ; 2.x failed to grow a fixed object.
  1000. ; Using a fixed segment for a local heap
  1001. ; is not valid and this is really a problem
  1002. ; with FORMBASE.
  1003. mov si,ax
  1004. cCall GlobalFlags,<si> ; Get flags
  1005. xchg ah, al
  1006. push ax
  1007. cCall GlobalSize,<si>
  1008. sub ax, handle ; Temorarily subtract out largest free
  1009. pop bx ; Get flags in BX
  1010. xor cx,cx
  1011. add ax,arg1
  1012. adc dx,cx ; Fail if DS attempts to grow
  1013. jnz dib_too_large ; beyond 64k.
  1014. add ax,18h ; since li_extra isn't guaranteed
  1015. adc dx,cx
  1016. jnz dib_too_large
  1017. add ax,[di].li_extra
  1018. adc dx,cx ; Fail if DS attempts to grow
  1019. jnz @F ; beyond 64k.
  1020. add ax, handle ; add back largest free
  1021. adc dx, cx
  1022. jnz @F
  1023. cmp ax,0FFF0h
  1024. jbe dln0dib
  1025. @@: mov ax,0FFF0h
  1026. xor dx,dx
  1027. jmps dln0dib
  1028. dib_too_large:
  1029. xor ax,ax
  1030. dlnexit1Dib:
  1031. jmp dlnexitdib
  1032. dln0dib:
  1033. test si,GA_FIXED ; Is DS fixed?
  1034. jnz dln1dib ; Yes, must grow in place
  1035. cmp bh,1 ; No, is lock count 1?
  1036. jne dln1dib ; No must grow in place if locked
  1037. or cl,GA_MOVEABLE ; Yes, okay to move even though locked
  1038. dln1dib:
  1039. push bx
  1040. cCall DibReAlloc,<ds,ax>
  1041. or ax,ax
  1042. jz dlnexitdib0
  1043. cCall GlobalSize,<si>
  1044. or dx,dx ; Did we get rounded up >= 64K?
  1045. jz @F ; No, OK
  1046. mov ax,0FFFFh ; This only happens under 386pmode
  1047. @@:
  1048. mov bx,ax
  1049. sub bx,la_freefixedsize
  1050. and bl,LA_MASK
  1051. mov di,ds:[pLocalHeap]
  1052. mov si,[di].hi_last
  1053. mov [bx].la_next,bx
  1054. mov [bx].la_prev,si
  1055. or byte ptr [bx].la_prev,LA_BUSY
  1056. mov [si].la_next,bx
  1057. ; Maintain the free list.
  1058. mov ax,[si].la_free_prev
  1059. mov [bx].la_free_prev,ax
  1060. mov [bx].la_free_next,bx
  1061. mov [bx].la_size,WORD PTR la_freefixedsize
  1062. push si
  1063. mov si,ax
  1064. mov [si].la_free_next,bx
  1065. pop si
  1066. mov [di].hi_last,bx
  1067. inc [di].hi_count
  1068. mov bx,si
  1069. call lfree
  1070. ; Don't do this... (bobgu 8/4/87)
  1071. ; stc
  1072. ; call lalign
  1073. ; call lcompact
  1074. mov ax,1
  1075. dlnexitdib0:
  1076. pop bx
  1077. dlnexitdib:
  1078. cEnd
  1079. sEnd CODE
  1080. externFP Far_lalign
  1081. externFP Far_lrepsetup
  1082. if KDEBUG
  1083. externFP Far_lfillCC
  1084. endif
  1085. sBegin NRESCODE
  1086. assumes CS,NRESCODE
  1087. assumes DS,NOTHING
  1088. assumes ES,NOTHING
  1089. cProc ILocalNotify,<PUBLIC,FAR>
  1090. ; parmD lpProc
  1091. cBegin nogen
  1092. mov bx,sp
  1093. mov ax,SS:[bx+4]
  1094. mov dx,SS:[bx+6]
  1095. mov bx,ds:[pLocalHeap]
  1096. xchg word ptr [bx].li_notify,ax
  1097. xchg word ptr [bx].li_notify+2,dx
  1098. ret 4
  1099. cEnd nogen
  1100. cProc LocalInit,<PUBLIC,FAR>,<ds,si,di>
  1101. parmW pseg
  1102. parmW pstart
  1103. parmW pend
  1104. cBegin
  1105. ; Init current DS if none passed.
  1106. mov cx,pseg
  1107. jcxz li1
  1108. mov ds,cx
  1109. li1:
  1110. ; Place local arena info at the beginning
  1111. mov bx,pstart
  1112. or bx,bx
  1113. jnz li2
  1114. cCall GlobalSize,<ds>
  1115. ; Here we must do a little checking... The global memory manager may have
  1116. ; rounded up the size on us so that the DS is >=64K! If this has happened,
  1117. ; we can simply ignore the extra (since app can't look at it anyway) and
  1118. ; pretend the DS is actually 0000FFFFH bytes big.
  1119. or dx,dx ; Did we get rounded up >= 64K?
  1120. jz li1a ; No, OK
  1121. mov ax,0FFFFH ; Pretend heap is 64K-1
  1122. li1a:
  1123. mov bx,ax
  1124. dec bx
  1125. xchg pend,bx
  1126. sub bx,pend
  1127. neg bx ; BX = first byte in arena
  1128. li2:
  1129. clc
  1130. call Far_lalign
  1131. mov bx,dx ; DX = addr of first block to use
  1132. ; OK, so here's how it works... In order to keep a free block list, there
  1133. ; are 4 blocks allocated initially. First is a dummy marker block that is
  1134. ; free but marked busy. Second is the local arena information block which
  1135. ; is a standard busy block. Third is the really big free block. And lastly
  1136. ; is another busy type free block. All free blocks have an extended header
  1137. ; in order to keep a free block list.
  1138. ; Reserve room for the first free busy block.
  1139. lea bx,[bx].la_freefixedsize ; move over first free block
  1140. push dx ; preserve first free block address
  1141. clc
  1142. call Far_lalign
  1143. mov bx,dx ; BX = arena info block address
  1144. pop dx ; DX = first block address
  1145. push dx ; * Save the address of the first
  1146. push bx ; * two block on the stack for later
  1147. ; DI = client address of info block.
  1148. lea di,[bx].la_fixedsize
  1149. xor ax,ax ; Zero local arena info
  1150. mov cx,pend
  1151. cmp bx,cx ; start > end?
  1152. ;;;;;;; jae lix
  1153. jb li21
  1154. pop dx ; clean up the stack first
  1155. pop dx
  1156. jmp lix
  1157. li21:
  1158. sub cx,di
  1159. call Far_lrepsetup
  1160. push di
  1161. rep stosw
  1162. pop di
  1163. lea bx,[di].SIZE LocalInfo
  1164. if KDEBUG
  1165. mov [di].hi_pstats,bx
  1166. add bx,SIZE LocalStats
  1167. ifdef DISABLE
  1168. ; Set the heap checking flag.
  1169. push es
  1170. push dx
  1171. cCall GlobalMasterHandle
  1172. mov es,dx
  1173. mov ax,es:[hi_check]
  1174. pop dx
  1175. pop es
  1176. else
  1177. push es
  1178. push _DATA
  1179. pop es
  1180. assumes es,DATA
  1181. ;
  1182. ; hi_check = 0;
  1183. ; if (DebugOptions & DBO_CHECKHEAP)
  1184. ; {
  1185. ; hi_check = 1
  1186. ; if (DebugOptions & DBO_CHECKFREE)
  1187. ; hi_check = 2;
  1188. ; }
  1189. ;
  1190. xor ax,ax
  1191. test es:DebugOptions,DBO_CHECKHEAP
  1192. jz @F
  1193. inc ax
  1194. test es:DebugOptions,DBO_CHECKFREE
  1195. jz @F
  1196. inc ax
  1197. @@:
  1198. assumes es,NOTHING
  1199. pop es
  1200. endif
  1201. mov [di].hi_check,ax
  1202. endif
  1203. ; set the rest of the heap info
  1204. mov byte ptr [di].hi_hdelta,32
  1205. mov byte ptr [di].hi_count,4
  1206. mov [di].hi_first,dx
  1207. mov word ptr [di].li_notify,codeOFFSET LocalNotifyDefault
  1208. mov word ptr [di].li_notify+2,codeBASE
  1209. mov word ptr [di].hi_hexpand,codeOFFSET lhexpand
  1210. mov [di].li_extra,512
  1211. mov [di].li_sig,LOCALHEAP_SIG
  1212. ; Move SI to first aligned block after info record
  1213. clc
  1214. call Far_lalign
  1215. mov si,dx
  1216. ; Move BX to last aligned block at end of local heap
  1217. mov bx,pend ; BX = end address
  1218. sub bx,la_freefixedsize ; Make room for an arena header
  1219. and bl,LA_MASK ; Align downwards to 4 byte boundary
  1220. cmp bx, si ; If heap is too small, the
  1221. ja @f ; supposed free block could be
  1222. xor ax, ax ; beyond the end block
  1223. jmp lix
  1224. @@:
  1225. ; Setup reserved pointer in DS to point to LocalInfo
  1226. mov [di].hi_last,bx
  1227. mov ds:[pLocalHeap],di
  1228. ; Finish linking entries in the local heap.
  1229. ;
  1230. ; DX = address of the first arena block. Free busy marker.
  1231. ; DI = address of the element which contains the local heap
  1232. ; information struc.
  1233. ; SI = address of large free block that is the initial heap.
  1234. ; BX = address of a zero length arena element that is used to
  1235. ; mark the end of the local heap.
  1236. ;
  1237. ;
  1238. ; This last arena element is always busy, with a length of
  1239. ; zero. This allows us to always calculate the length of an
  1240. ; arena entry by subtracting the address of the arena element
  1241. ; from the hi_next field of the arena element (see lsize subr)
  1242. pop di ; Get the address of the first two
  1243. pop dx ; ... blocks off the stack
  1244. ; Setup first block in arena, busy free block.
  1245. xchg bx,dx ;bx = first block (temporarily)
  1246. lea ax,[bx+LA_BUSY] ; ...as a busy block
  1247. mov [bx].la_prev,ax ; point to self
  1248. mov [bx].la_next,di ; point to next
  1249. mov [bx].la_free_prev,bx ; previous free block is self
  1250. mov [bx].la_free_next,si ; next free is large block
  1251. mov [bx].la_size,WORD PTR la_freefixedsize ; set the block size
  1252. xchg bx,dx ; back to normal
  1253. ; Setup block that contains info structure.
  1254. xchg dx,bx
  1255. lea ax,[bx+LA_BUSY] ; ...as a busy block
  1256. xchg dx,bx
  1257. mov [di].la_prev,ax ; point to previous block
  1258. mov [di].la_next,si ; point to next block
  1259. ; Setup large free block with extended free block header.
  1260. mov [si].la_prev,di ; Point middle block to first and
  1261. mov [si].la_next,bx ; last blocks
  1262. mov [si].la_free_prev,dx ; previous free block
  1263. mov [si].la_free_next,bx ; next free block
  1264. mov ax,bx
  1265. sub ax,si
  1266. mov [si].la_size,ax ; length of free block
  1267. if KDEBUG
  1268. xchg si,bx ; BX = large free block
  1269. call Far_lfillCC ; Fill with 0CCh
  1270. xchg si,bx
  1271. endif
  1272. ; Setup last free block with extended header.
  1273. mov [bx].la_next,bx ; Point last block to middle and itself
  1274. lea ax,[si+LA_BUSY] ; ...as a busy block
  1275. mov [bx].la_prev,ax
  1276. mov [bx].la_free_prev,si ; previous free block
  1277. mov [bx].la_free_next,bx ; next free block is self
  1278. mov [bx].la_size,WORD PTR la_freefixedsize ; set the block size
  1279. ; Set the minimum size in arena header.
  1280. mov bx,ds:[pLocalHeap]
  1281. mov ax,[bx].hi_last
  1282. add ax,SIZE LocalArenaFree
  1283. sub ax,[bx].hi_first
  1284. mov [bx].li_minsize,ax
  1285. cCall GlobalLock,<ds> ; Make moveable DS initially locked.
  1286. ; (see LocalNotifyDefault)
  1287. mov al,1
  1288. lix:
  1289. mov cx,ax
  1290. cEnd
  1291. ;-----------------------------------------------------------------------;
  1292. ; LocalCountFree ;
  1293. ; ;
  1294. ; Return the count of free bytes in the local heap. This was motivated ;
  1295. ; by the InitApp routines that want at least 4K available to continue ;
  1296. ; the app running. ;
  1297. ; ;
  1298. ; Arguments: ;
  1299. ; DS = heap segment ;
  1300. ; ;
  1301. ; Returns: ;
  1302. ; AX = free bytes in local heap ;
  1303. ; ;
  1304. ; Error Returns: ;
  1305. ; ;
  1306. ; Registers Preserved: ;
  1307. ; all ;
  1308. ; ;
  1309. ; Registers Destroyed: ;
  1310. ; ;
  1311. ; Calls: ;
  1312. ; ;
  1313. ; History: ;
  1314. ; ;
  1315. ; Sat Aug 15, 1987 04:35:55p -by- Bob Gunderson [bobgu] ;
  1316. ; Wrote it. ;
  1317. ;-----------------------------------------------------------------------;
  1318. cProc LocalCountFree,<PUBLIC,FAR>
  1319. cBegin nogen
  1320. push di
  1321. push si
  1322. mov di,pLocalHeap
  1323. lea si, [di].li_sig
  1324. cCall FarValidatePointer,<ds,si>
  1325. or ax, ax ; OK pointer?
  1326. jz countexit ; no, just exit
  1327. xor ax,ax ; start with 0 bytes free
  1328. cmp [di].li_sig, LOCALHEAP_SIG
  1329. jne countexit ; No local heap!!
  1330. mov si,[di].hi_last ; sentenal block
  1331. mov di,[di].hi_first ; arena header
  1332. mov di,[di].la_free_next ; first free block
  1333. countloop:
  1334. cmp di,si
  1335. jz countexit
  1336. add ax,[di].la_size ; count size of this block
  1337. sub ax,SIZE LocalArenaFree ; less block overhead
  1338. mov di,[di].la_free_next ; next free block
  1339. jmp countloop
  1340. countexit:
  1341. pop si
  1342. pop di
  1343. ret
  1344. cEnd nogen
  1345. ;-----------------------------------------------------------------------;
  1346. ; LocalHeapSize ;
  1347. ; ;
  1348. ; Return the # bytes allocated to the local heap. ;
  1349. ; ;
  1350. ; Arguments: ;
  1351. ; DS = heap segment ;
  1352. ; ;
  1353. ; Returns: ;
  1354. ; AX = size of local heap ;
  1355. ; ;
  1356. ; Error Returns: ;
  1357. ; ;
  1358. ; Registers Preserved: ;
  1359. ; CX,DX,SI,SI,DS,ES ;
  1360. ; ;
  1361. ; Registers Destroyed: ;
  1362. ; BX ;
  1363. ; ;
  1364. ; Calls: ;
  1365. ; ;
  1366. ; History: ;
  1367. ; ;
  1368. ; Sat Aug 15, 1987 04:35:55p -by- Bob Gunderson [bobgu] ;
  1369. ; Wrote it. ;
  1370. ;-----------------------------------------------------------------------;
  1371. cProc LocalHeapSize,<PUBLIC,FAR>
  1372. cBegin nogen
  1373. mov bx,pLocalHeap
  1374. mov ax,[bx].hi_last
  1375. sub ax,[bx].hi_first
  1376. ret
  1377. cEnd nogen
  1378. ;-----------------------------------------------------------------------;
  1379. ; LocalHandleDelta ;
  1380. ; ;
  1381. ; Change the number of handles to allocate each time ;
  1382. ; ;
  1383. ; Arguments: ;
  1384. ; delta = new # of handles or 0 ;
  1385. ; DS = heap segment ;
  1386. ; ;
  1387. ; Returns: ;
  1388. ; AX = new number of handles ;
  1389. ; ;
  1390. ; Error Returns: ;
  1391. ; ;
  1392. ; Registers Preserved: ;
  1393. ; CX,DX,SI,SI,DS,ES ;
  1394. ; ;
  1395. ; Registers Destroyed: ;
  1396. ; BX ;
  1397. ; ;
  1398. ; Calls: ;
  1399. ; ;
  1400. ; History: ;
  1401. ; ;
  1402. ;-----------------------------------------------------------------------;
  1403. cProc LocalHandleDelta,<PUBLIC,FAR>
  1404. parmW delta
  1405. cBegin
  1406. mov bx,pLocalHeap
  1407. mov ax, delta
  1408. or ax, ax ; Zero means return present value
  1409. jz return_present_value
  1410. mov ax, delta
  1411. mov [bx].hi_hdelta, ax ; Set new value
  1412. return_present_value:
  1413. mov ax, [bx].hi_hdelta
  1414. cEnd
  1415. sEnd NRESCODE
  1416. end