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.

1182 lines
35 KiB

  1. // Ruler
  2. // 1 2 3 4 5 6 7 8
  3. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  4. /********************************************************************/
  5. /* */
  6. /* The standard layout. */
  7. /* */
  8. /* The standard layout for 'cpp' files in this code is as */
  9. /* follows: */
  10. /* */
  11. /* 1. Include files. */
  12. /* 2. Constants local to the class. */
  13. /* 3. Data structures local to the class. */
  14. /* 4. Data initializations. */
  15. /* 5. Static functions. */
  16. /* 6. Class functions. */
  17. /* */
  18. /* The constructor is typically the first function, class */
  19. /* member functions appear in alphabetical order with the */
  20. /* destructor appearing at the end of the file. Any section */
  21. /* or function this is not required is simply omitted. */
  22. /* */
  23. /********************************************************************/
  24. #include "InterfacePCH.hpp"
  25. #include "Dll.hpp"
  26. #include "List.hpp"
  27. #include "New.hpp"
  28. #include "Sharelock.hpp"
  29. #include "SmpHeap.hpp"
  30. #include "Tls.hpp"
  31. /********************************************************************/
  32. /* */
  33. /* Structures local to the class. */
  34. /* */
  35. /* The structures supplied here describe the layout of the */
  36. /* private per thread heap structures. */
  37. /* */
  38. /********************************************************************/
  39. typedef struct PRIVATE_HEAP : public LIST
  40. {
  41. SMP_HEAP_TYPE Heap;
  42. }
  43. PRIVATE_HEAP;
  44. /********************************************************************/
  45. /* */
  46. /* Static data structures. */
  47. /* */
  48. /* The static data structures are initialized and prepared for */
  49. /* use here. */
  50. /* */
  51. /********************************************************************/
  52. STATIC SHARELOCK Sharelock;
  53. /********************************************************************/
  54. /* */
  55. /* Class constructor. */
  56. /* */
  57. /* The overall structure and layout of the heap is controlled */
  58. /* by the various constants and calls made in this function. */
  59. /* There is a significant amount of flexibility available to */
  60. /* a heap which can lead to them having dramatically different */
  61. /* properties. */
  62. /* */
  63. /********************************************************************/
  64. SMP_HEAP::SMP_HEAP
  65. (
  66. int MaxFreeSpace,
  67. bool Recycle,
  68. bool SingleImage,
  69. bool ThreadSafe,
  70. bool DeleteHeapOnExit
  71. ) :
  72. //
  73. // Call the constructors for the contained classes.
  74. //
  75. MaxFreeSpace(MaxFreeSpace),
  76. Recycle(Recycle),
  77. SingleImage(True),
  78. ThreadSafe(ThreadSafe),
  79. SMP_HEAP_TYPE( 0,false,true,true )
  80. {
  81. //
  82. // Setup various control variables.
  83. //
  84. Active = false;
  85. DeleteOnExit = DeleteHeapOnExit;
  86. //
  87. // Create the linked list headers and a thread
  88. // local store variable to point at each threads
  89. // private heap.
  90. //
  91. ActiveHeaps = ((LIST*) SMP_HEAP_TYPE::New( sizeof(LIST) ));
  92. DllEvents = ((DLL*) SMP_HEAP_TYPE::New( sizeof(DLL) ));
  93. FreeHeaps = ((LIST*) SMP_HEAP_TYPE::New( sizeof(LIST) ));
  94. HeapWalk = NULL;
  95. Tls = ((TLS*) SMP_HEAP_TYPE::New( sizeof(TLS) ));
  96. //
  97. // We can only activate the the heap if we manage
  98. // to allocate space we requested.
  99. //
  100. if
  101. (
  102. (ActiveHeaps != NULL)
  103. &&
  104. (DllEvents != NULL)
  105. &&
  106. (FreeHeaps != NULL)
  107. &&
  108. (Tls != NULL)
  109. )
  110. {
  111. //
  112. // Execute the constructors for each linked list
  113. // and for the thread local store.
  114. //
  115. PLACEMENT_NEW( ActiveHeaps,LIST );
  116. #ifdef COMPILING_ROCKALL_DLL
  117. PLACEMENT_NEW( DllEvents,DLL )( ThreadDetach,this );
  118. #endif
  119. PLACEMENT_NEW( FreeHeaps,LIST );
  120. PLACEMENT_NEW( Tls,TLS );
  121. //
  122. // Activate the heap.
  123. //
  124. ActiveLocks = 0;
  125. Active = true;
  126. }
  127. }
  128. /********************************************************************/
  129. /* */
  130. /* Memory deallocation. */
  131. /* */
  132. /* When we delete an allocation we try to delete it in the */
  133. /* private per thread heap if it exists. */
  134. /* */
  135. /********************************************************************/
  136. bool SMP_HEAP::Delete( void *Address,int Size )
  137. {
  138. //
  139. // Although it is very rare there is a chance
  140. // that we failed to build the basic heap structures.
  141. //
  142. if ( Active )
  143. {
  144. REGISTER PRIVATE_HEAP *PrivateHeap =
  145. ((PRIVATE_HEAP*) Tls -> GetPointer());
  146. //
  147. // We need to examine the TLS pointer to make
  148. // sure we have a heap for the current thread.
  149. // If not we just use the internal heap.
  150. //
  151. if ( PrivateHeap != NULL )
  152. { return (PrivateHeap -> Heap.Delete( Address,Size )); }
  153. else
  154. { return (SMP_HEAP_TYPE::Delete( Address,Size )); }
  155. }
  156. else
  157. { return false; }
  158. }
  159. /********************************************************************/
  160. /* */
  161. /* Delete all allocations. */
  162. /* */
  163. /* We walk the list of all the heaps and instruct each heap */
  164. /* to delete everything. */
  165. /* */
  166. /********************************************************************/
  167. void SMP_HEAP::DeleteAll( bool Recycle )
  168. {
  169. //
  170. // Although it is very rare there is a chance
  171. // that we failed to build the basic heap structures.
  172. //
  173. if ( Active )
  174. {
  175. REGISTER PRIVATE_HEAP *Current;
  176. //
  177. // Claim a process wide shared lock
  178. // to ensure the list of heaps does
  179. // not change until we have finished.
  180. //
  181. Sharelock.ClaimShareLock();
  182. //
  183. // You just have to hope the user knows
  184. // what they are doing as everything gets
  185. // blown away.
  186. //
  187. for
  188. (
  189. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First());
  190. (Current != NULL);
  191. Current = ((PRIVATE_HEAP*) Current -> Next())
  192. )
  193. { Current -> Heap.DeleteAll( Recycle ); }
  194. //
  195. // Release the lock.
  196. //
  197. Sharelock.ReleaseShareLock();
  198. //
  199. // Claim a process wide exclusive lock
  200. // to ensure the list of heaps does
  201. // not change until we have finished.
  202. //
  203. Sharelock.ClaimExclusiveLock();
  204. //
  205. // We walk the free list of heaps and
  206. // delete everything.
  207. //
  208. for
  209. (
  210. Current = ((PRIVATE_HEAP*) FreeHeaps -> First());
  211. Current != NULL;
  212. Current = ((PRIVATE_HEAP*) FreeHeaps -> First())
  213. )
  214. {
  215. //
  216. // Delete each heap from the free list,
  217. // call the destructor and delete any
  218. // associated space.
  219. //
  220. Current -> Delete( FreeHeaps );
  221. PLACEMENT_DELETE( Current,PRIVATE_HEAP );
  222. SMP_HEAP_TYPE::Delete( Current );
  223. }
  224. //
  225. // Release the lock.
  226. //
  227. Sharelock.ReleaseExclusiveLock();
  228. }
  229. }
  230. /********************************************************************/
  231. /* */
  232. /* Memory allocation details. */
  233. /* */
  234. /* When we are asked for details we try to the private per */
  235. /* thread heap if it exists. */
  236. /* */
  237. /********************************************************************/
  238. bool SMP_HEAP::Details( void *Address,int *Space )
  239. {
  240. //
  241. // Although it is very rare there is a chance
  242. // that we failed to build the basic heap structures.
  243. //
  244. if ( Active )
  245. {
  246. REGISTER PRIVATE_HEAP *PrivateHeap =
  247. ((PRIVATE_HEAP*) Tls -> GetPointer());
  248. //
  249. // We need to examine the TLS pointer to make
  250. // sure we have a heap for the current thread.
  251. // If not we just use the internal heap.
  252. //
  253. if ( PrivateHeap != NULL )
  254. { return (PrivateHeap -> Heap.Details( Address,Space )); }
  255. else
  256. { return (SMP_HEAP_TYPE::Details( Address,Space )); }
  257. }
  258. else
  259. { return false; }
  260. }
  261. /********************************************************************/
  262. /* */
  263. /* Extract the private heap. */
  264. /* */
  265. /* We need to provide all threads with a private heap. When */
  266. /* we discover we need another heap we either recycle an */
  267. /* existing heap or create a new one. */
  268. /* */
  269. /********************************************************************/
  270. PRIVATE_HEAP *SMP_HEAP::GetPrivateHeap( void )
  271. {
  272. REGISTER PRIVATE_HEAP *PrivateHeap = ((PRIVATE_HEAP*) Tls -> GetPointer());
  273. //
  274. // We need to examine the TLS pointer to make
  275. // sure we have a heap for the current thread.
  276. // If not we just create a new heap.
  277. //
  278. if ( PrivateHeap == NULL )
  279. {
  280. //
  281. // Claim a process wide exclusive lock
  282. // to ensure the list of heaps does
  283. // not change until we have finished.
  284. //
  285. Sharelock.ClaimExclusiveLock();
  286. //
  287. // When there is an available free heap
  288. // then extract it from the free list.
  289. //
  290. if ( (PrivateHeap = ((PRIVATE_HEAP*) FreeHeaps -> First())) != NULL )
  291. {
  292. //
  293. // Delete the heap from the list of
  294. // of free heaps.
  295. //
  296. PrivateHeap -> Delete( FreeHeaps );
  297. }
  298. //
  299. // When there is no available free heap then
  300. // we try to make a new heap.
  301. //
  302. if ( PrivateHeap == NULL )
  303. {
  304. //
  305. // Release the lock.
  306. //
  307. Sharelock.ReleaseExclusiveLock();
  308. //
  309. // Allocate space for the new private per
  310. // thread heap.
  311. //
  312. PrivateHeap =
  313. ((PRIVATE_HEAP*) SMP_HEAP_TYPE::New( sizeof(PRIVATE_HEAP) ));
  314. //
  315. // We need to ensure that the allocation
  316. // worked before we try to add it into
  317. // the list of active heaps.
  318. //
  319. if ( PrivateHeap != NULL )
  320. {
  321. //
  322. // Activate the new heap.
  323. //
  324. PLACEMENT_NEW( PrivateHeap,LIST );
  325. PLACEMENT_NEW( & PrivateHeap -> Heap,SMP_HEAP_TYPE )
  326. (
  327. MaxFreeSpace,
  328. Recycle,
  329. SingleImage,
  330. ThreadSafe
  331. );
  332. //
  333. // If the heap constructor failed, then
  334. // do not put this heap in the list of
  335. // active heaps, and return NULL back to
  336. // the caller. A side-effect of this is
  337. // that the allocation for the PrivateHeap
  338. // will be leaked.
  339. //
  340. if (! PrivateHeap->Heap.Available())
  341. {
  342. PrivateHeap = NULL;
  343. }
  344. }
  345. //
  346. // Claim a process wide exclusive lock
  347. // to ensure the list of heaps does
  348. // not change until we have finished.
  349. //
  350. Sharelock.ClaimExclusiveLock();
  351. }
  352. //
  353. // We would expect to have a new heap by this
  354. // point. If not then we just exit.
  355. //
  356. if ( PrivateHeap != NULL )
  357. {
  358. //
  359. // Insert the new heap in the list
  360. // of active heaps.
  361. //
  362. PrivateHeap -> Insert( ActiveHeaps );
  363. //
  364. // Nasty: we may have an outstanding lock
  365. // on the rest of the heaps. If so claim
  366. // it for this heap as well.
  367. //
  368. if ( ActiveLocks > 0 )
  369. { PrivateHeap -> Heap.LockAll(); }
  370. //
  371. // Update the TLS pointer.
  372. //
  373. Tls -> SetPointer( ((VOID*) PrivateHeap) );
  374. }
  375. //
  376. // Release the lock.
  377. //
  378. Sharelock.ReleaseExclusiveLock();
  379. }
  380. return PrivateHeap;
  381. }
  382. /********************************************************************/
  383. /* */
  384. /* A known area. */
  385. /* */
  386. /* When we are asked about an address we try to the private per */
  387. /* thread heap if it exists. */
  388. /* */
  389. /********************************************************************/
  390. bool SMP_HEAP::KnownArea( void *Address )
  391. {
  392. //
  393. // Although it is very rare there is a chance
  394. // that we failed to build the basic heap structures.
  395. //
  396. if ( Active )
  397. {
  398. REGISTER PRIVATE_HEAP *PrivateHeap =
  399. ((PRIVATE_HEAP*) Tls -> GetPointer());
  400. //
  401. // We need to examine the TLS pointer to make
  402. // sure we have a heap for the current thread.
  403. // If not we just use the internal heap.
  404. //
  405. if ( PrivateHeap != NULL )
  406. { return (PrivateHeap -> Heap.KnownArea( Address )); }
  407. else
  408. { return (SMP_HEAP_TYPE::KnownArea( Address )); }
  409. }
  410. else
  411. { return false; }
  412. }
  413. /********************************************************************/
  414. /* */
  415. /* Claim all the heap locks. */
  416. /* */
  417. /* We claim all of the heap locks so that it is safe to do */
  418. /* operations like walking all of the heaps. */
  419. /* */
  420. /********************************************************************/
  421. void SMP_HEAP::LockAll( VOID )
  422. {
  423. //
  424. // Although it is very rare there is a chance
  425. // that we failed to build the basic heap structures.
  426. //
  427. if ( Active )
  428. {
  429. REGISTER PRIVATE_HEAP *Current;
  430. //
  431. // Claim a process wide shared lock
  432. // to ensure the list of heaps does
  433. // not change until we have finished.
  434. //
  435. Sharelock.ClaimShareLock();
  436. //
  437. // Nasty: We may actually create or delete
  438. // a heap between locking all the heaps and
  439. // unlocking them. Thus, we need to keep a
  440. // count of the outstanding locks to keep
  441. // this all consistent.
  442. //
  443. ASSEMBLY::AtomicIncrement( ((SBIT32*) & ActiveLocks) );
  444. //
  445. // You just have to hope the user knows
  446. // what they are doing as we claim all
  447. // of the heap locks.
  448. //
  449. for
  450. (
  451. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First());
  452. (Current != NULL);
  453. Current = ((PRIVATE_HEAP*) Current -> Next())
  454. )
  455. { Current -> Heap.LockAll(); }
  456. //
  457. // Release the lock.
  458. //
  459. Sharelock.ReleaseShareLock();
  460. }
  461. }
  462. /********************************************************************/
  463. /* */
  464. /* Multiple memory deallocations. */
  465. /* */
  466. /* When we delete multiple allocations we try to delete them on */
  467. /* the private per thread heap if it exists. */
  468. /* */
  469. /********************************************************************/
  470. bool SMP_HEAP::MultipleDelete
  471. (
  472. int Actual,
  473. void *Array[],
  474. int Size
  475. )
  476. {
  477. //
  478. // Although it is very rare there is a chance
  479. // that we failed to build the basic heap structures.
  480. //
  481. if ( Active )
  482. {
  483. REGISTER PRIVATE_HEAP *PrivateHeap =
  484. ((PRIVATE_HEAP*) Tls -> GetPointer());
  485. //
  486. // We need to examine the TLS pointer to make
  487. // sure we have a heap for the current thread.
  488. // If not we just use the internal heap.
  489. //
  490. if ( PrivateHeap != NULL )
  491. { return (PrivateHeap -> Heap.MultipleDelete(Actual,Array,Size)); }
  492. else
  493. { return (SMP_HEAP_TYPE::MultipleDelete( Actual,Array,Size )); }
  494. }
  495. else
  496. { return false; }
  497. }
  498. /********************************************************************/
  499. /* */
  500. /* Multiple memory allocations. */
  501. /* */
  502. /* We allocate space for the current thread from the local */
  503. /* private per thread heap. If we do not have a local private */
  504. /* per thread heap then we create one and use it. */
  505. /* */
  506. /********************************************************************/
  507. bool SMP_HEAP::MultipleNew
  508. (
  509. int *Actual,
  510. void *Array[],
  511. int Requested,
  512. int Size,
  513. int *Space,
  514. bool Zero
  515. )
  516. {
  517. //
  518. // Although it is very rare there is a chance
  519. // that we failed to build the basic heap structures.
  520. //
  521. if ( Active )
  522. {
  523. REGISTER PRIVATE_HEAP *PrivateHeap = GetPrivateHeap();
  524. //
  525. // We need to examine private heap to make
  526. // sure we have a heap for the current thread.
  527. //
  528. if ( PrivateHeap != NULL )
  529. {
  530. //
  531. // Allocate the memory requested on the local
  532. // private per thread heap.
  533. //
  534. return
  535. (
  536. PrivateHeap -> Heap.MultipleNew
  537. (
  538. Actual,
  539. Array,
  540. Requested,
  541. Size,
  542. Space,
  543. Zero
  544. )
  545. );
  546. }
  547. else
  548. {
  549. //
  550. // We were unable to create a new heap
  551. // so exit.
  552. //
  553. (*Actual) = 0;
  554. return false;
  555. }
  556. }
  557. else
  558. {
  559. //
  560. // We are not active yet so exit.
  561. //
  562. (*Actual) = 0;
  563. return false;
  564. }
  565. }
  566. /********************************************************************/
  567. /* */
  568. /* Memory allocation. */
  569. /* */
  570. /* We allocate space for the current thread from the local */
  571. /* private per thread heap. If we do not have a local private */
  572. /* per thread heap then we create one and use it. */
  573. /* */
  574. /********************************************************************/
  575. void *SMP_HEAP::New( int Size,int *Space,bool Zero )
  576. {
  577. //
  578. // Although it is very rare there is a chance
  579. // that we failed to build the basic heap structures.
  580. //
  581. if ( Active )
  582. {
  583. REGISTER PRIVATE_HEAP *PrivateHeap = GetPrivateHeap();
  584. //
  585. // We need to examine private heap to make
  586. // sure we have a heap for the current thread.
  587. //
  588. if ( PrivateHeap != NULL )
  589. { return (PrivateHeap -> Heap.New( Size,Space,Zero )); }
  590. else
  591. { return NULL; }
  592. }
  593. else
  594. { return NULL; }
  595. }
  596. /********************************************************************/
  597. /* */
  598. /* Memory reallocation. */
  599. /* */
  600. /* We reallocate space for the current thread on the local */
  601. /* private per thread heap. If we do not have a local private */
  602. /* per thread heap then we create one and use it. */
  603. /* */
  604. /********************************************************************/
  605. void *SMP_HEAP::Resize
  606. (
  607. void *Address,
  608. int NewSize,
  609. int Move,
  610. int *Space,
  611. bool NoDelete,
  612. bool Zero
  613. )
  614. {
  615. //
  616. // Although it is very rare there is a chance
  617. // that we failed to build the basic heap structures.
  618. //
  619. if ( Active )
  620. {
  621. REGISTER PRIVATE_HEAP *PrivateHeap = GetPrivateHeap();
  622. //
  623. // We need to examine private heap to make
  624. // sure we have a heap for the current thread.
  625. //
  626. if ( PrivateHeap != NULL )
  627. {
  628. //
  629. // Reallocate the memory requested on
  630. // the local private per thread heap.
  631. //
  632. return
  633. (
  634. PrivateHeap -> Heap.Resize
  635. (
  636. Address,
  637. NewSize,
  638. Move,
  639. Space,
  640. NoDelete,
  641. Zero
  642. )
  643. );
  644. }
  645. else
  646. { return NULL; }
  647. }
  648. else
  649. { return NULL; }
  650. }
  651. /********************************************************************/
  652. /* */
  653. /* Special memory allocation. */
  654. /* */
  655. /* We sometimes need to allocate some memory from the internal */
  656. /* memory allocator which lives for the lifetime of the heap. */
  657. /* */
  658. /********************************************************************/
  659. void *SMP_HEAP::SpecialNew( int Size )
  660. { return SMP_HEAP_TYPE::New( Size ); }
  661. /********************************************************************/
  662. /* */
  663. /* Delete a local heap. */
  664. /* */
  665. /* Delete a local per thread heap and return all the outstanding */
  666. /* memory to the operating system. */
  667. /* */
  668. /********************************************************************/
  669. void SMP_HEAP::ThreadDetach( void *Parameter,int Reason )
  670. {
  671. //
  672. // We only take any action on a thread detach
  673. // notification. All other notifications are
  674. // not actioned.
  675. //
  676. if ( Reason == DLL_THREAD_DETACH )
  677. {
  678. REGISTER SMP_HEAP *SmpHeap = ((SMP_HEAP*) Parameter);
  679. //
  680. // Claim a process wide exclusive lock
  681. // to ensure the list of heaps does
  682. // not change until we have finished.
  683. //
  684. Sharelock.ClaimExclusiveLock();
  685. //
  686. // There is a nasty situation where the
  687. // destructor is called before a thread
  688. // fully terminates so ensure the heap
  689. // is still active.
  690. //
  691. if ( SmpHeap -> Active )
  692. {
  693. REGISTER PRIVATE_HEAP *PrivateHeap =
  694. ((PRIVATE_HEAP*) SmpHeap -> Tls -> GetPointer());
  695. //
  696. // We need to examine the TLS pointer to make
  697. // sure we have a heap for the current thread.
  698. // If not we just use the internal heap.
  699. //
  700. if ( PrivateHeap != NULL )
  701. {
  702. //
  703. // Update the TLS pointer.
  704. //
  705. SmpHeap -> Tls -> SetPointer( NULL );
  706. //
  707. // Insert the new heap in the list
  708. // of active heaps.
  709. //
  710. PrivateHeap -> Delete( SmpHeap -> ActiveHeaps );
  711. //
  712. // When we are not allowed to delete
  713. // the heap we put it on the free list.
  714. //
  715. if ( ! SmpHeap -> DeleteOnExit )
  716. { PrivateHeap -> Insert( SmpHeap -> FreeHeaps ); }
  717. //
  718. // Nasty: we may have an outstanding lock
  719. // on this heap. If so then free it.
  720. //
  721. if ( SmpHeap -> ActiveLocks > 0 )
  722. { PrivateHeap -> Heap.UnlockAll(); }
  723. //
  724. // Release the lock.
  725. //
  726. Sharelock.ReleaseExclusiveLock();
  727. //
  728. // When we are allowed to delete the
  729. // heap we do it here.
  730. //
  731. if ( ! SmpHeap -> DeleteOnExit )
  732. {
  733. //
  734. // Truncate the heap to remove any
  735. // unwanted space.
  736. //
  737. PrivateHeap -> Heap.Truncate( 0 );
  738. }
  739. else
  740. {
  741. #ifdef COMPLAIN_ABOUT_SMP_HEAP_LEAKS
  742. //
  743. // We have finished with the private
  744. // heap so now is a good time to complain
  745. // about leaks.
  746. //
  747. PrivateHeap -> Heap.HeapLeaks();
  748. #endif
  749. //
  750. // We have finished with the private
  751. // heap so delete it.
  752. //
  753. PLACEMENT_DELETE( PrivateHeap,PRIVATE_HEAP );
  754. SmpHeap -> SMP_HEAP_TYPE::Delete( PrivateHeap );
  755. }
  756. }
  757. else
  758. { Sharelock.ReleaseExclusiveLock(); }
  759. }
  760. else
  761. { Sharelock.ReleaseExclusiveLock(); }
  762. }
  763. }
  764. /********************************************************************/
  765. /* */
  766. /* Truncate the heap. */
  767. /* */
  768. /* We need to truncate the heap. This is pretty much a null */
  769. /* call as we do this as we go along anyway. The only thing we */
  770. /* can do is free any space the user suggested keeping earlier. */
  771. /* */
  772. /********************************************************************/
  773. bool SMP_HEAP::Truncate( int MaxFreeSpace )
  774. {
  775. REGISTER bool Result = true;
  776. //
  777. // Although it is very rare there is a chance
  778. // that we failed to build the basic heap structures.
  779. //
  780. if ( Active )
  781. {
  782. REGISTER PRIVATE_HEAP *Current;
  783. //
  784. // Claim a process wide shared lock
  785. // to ensure the list of heaps does
  786. // not change until we have finished.
  787. //
  788. Sharelock.ClaimShareLock();
  789. //
  790. // You just have to hope the user knows
  791. // what they are doing as we are truncating
  792. // all of the heaps.
  793. //
  794. for
  795. (
  796. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First());
  797. (Current != NULL);
  798. Current = ((PRIVATE_HEAP*) Current -> Next())
  799. )
  800. {
  801. //
  802. // If faulty delete is noted during the
  803. // cache flushes then exit with the
  804. // correct status.
  805. //
  806. if ( ! Current -> Heap.Truncate( MaxFreeSpace ) )
  807. { Result = false; }
  808. }
  809. //
  810. // Release the lock.
  811. //
  812. Sharelock.ReleaseShareLock();
  813. }
  814. return Result;
  815. }
  816. /********************************************************************/
  817. /* */
  818. /* Release all the heap locks. */
  819. /* */
  820. /* We unlock all of the heap locks so normal processing can */
  821. /* continue on the heaps. */
  822. /* */
  823. /********************************************************************/
  824. void SMP_HEAP::UnlockAll( VOID )
  825. {
  826. //
  827. // Although it is very rare there is a chance
  828. // that we failed to build the basic heap structures.
  829. //
  830. if ( Active )
  831. {
  832. REGISTER PRIVATE_HEAP *Current;
  833. //
  834. // Claim a process wide shared lock
  835. // to ensure the list of heaps does
  836. // not change until we have finished.
  837. //
  838. Sharelock.ClaimShareLock();
  839. //
  840. // You just have to hope the user knows
  841. // what they are doing as we claim all
  842. // of the heap locks.
  843. //
  844. for
  845. (
  846. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First());
  847. (Current != NULL);
  848. Current = ((PRIVATE_HEAP*) Current -> Next())
  849. )
  850. { Current -> Heap.UnlockAll(); }
  851. //
  852. // Nasty: We may actually create or delete
  853. // a private heap for a thread between
  854. // locking an 'SMP_HEAP' and unlocking it.
  855. // Thus, we need to keep a count of the
  856. // outstanding locks to keep this all
  857. // consistent.
  858. //
  859. ASSEMBLY::AtomicDecrement( ((SBIT32*) & ActiveLocks) );
  860. //
  861. // Release the lock.
  862. //
  863. Sharelock.ReleaseShareLock();
  864. }
  865. }
  866. /********************************************************************/
  867. /* */
  868. /* Verify a memory allocation details. */
  869. /* */
  870. /* When we verify an allocation we try to verify it in the */
  871. /* private per thread heap if it exists. */
  872. /* */
  873. /********************************************************************/
  874. bool SMP_HEAP::Verify( void *Address,int *Space )
  875. {
  876. //
  877. // Although it is very rare there is a chance
  878. // that we failed to build the basic heap structures.
  879. //
  880. if ( Active )
  881. {
  882. REGISTER PRIVATE_HEAP *PrivateHeap =
  883. ((PRIVATE_HEAP*) Tls -> GetPointer());
  884. //
  885. // We need to examine the TLS pointer to make
  886. // sure we have a heap for the current thread.
  887. // If not we just use the internal heap.
  888. //
  889. if ( PrivateHeap != NULL )
  890. { return (PrivateHeap -> Heap.Verify( Address,Space )); }
  891. else
  892. { return (SMP_HEAP_TYPE::Verify( Address,Space )); }
  893. }
  894. else
  895. { return false; }
  896. }
  897. /********************************************************************/
  898. /* */
  899. /* Walk the heap. */
  900. /* */
  901. /* We have been asked to walk the heap. It is hard to know */
  902. /* why anybody might want to do this given the rest of the */
  903. /* functionality available. Nonetheless, we just do what is */
  904. /* required to keep everyone happy. */
  905. /* */
  906. /********************************************************************/
  907. bool SMP_HEAP::Walk( bool *Activity,void **Address,int *Space )
  908. {
  909. //
  910. // Claim a process wide shared lock
  911. // to ensure the list of heaps does
  912. // not change until we have finished.
  913. //
  914. Sharelock.ClaimShareLock();
  915. //
  916. // Nasty, in 'SMP_HEAP' we have multiple heaps
  917. // to walk so if we don't have a current heap
  918. // then just select the first available.
  919. //
  920. if ( ((*Address) == NULL) || (HeapWalk == NULL) )
  921. { HeapWalk = ((PRIVATE_HEAP*) ActiveHeaps -> First()); }
  922. //
  923. // Walk the heap. When we come to the end of
  924. // the current heap then move on to the next
  925. // heap.
  926. //
  927. while
  928. (
  929. (HeapWalk != NULL)
  930. &&
  931. (! HeapWalk -> Heap.Walk( Activity,Address,Space ))
  932. )
  933. { HeapWalk = ((PRIVATE_HEAP*) HeapWalk -> Next()); }
  934. //
  935. // Release the lock.
  936. //
  937. Sharelock.ReleaseShareLock();
  938. return (HeapWalk != NULL);
  939. }
  940. /********************************************************************/
  941. /* */
  942. /* Class destructor. */
  943. /* */
  944. /* Destory the heap. */
  945. /* */
  946. /********************************************************************/
  947. SMP_HEAP::~SMP_HEAP( void )
  948. {
  949. //
  950. // Although it is very rare there is a chance
  951. // that we failed to build the basic heap structures.
  952. //
  953. if ( Active )
  954. {
  955. REGISTER PRIVATE_HEAP *Current;
  956. //
  957. // Deactivate the heap.
  958. //
  959. Active = false;
  960. //
  961. // Claim a process wide exclusive lock
  962. // to ensure the list of heaps does
  963. // not change until we have finished.
  964. //
  965. Sharelock.ClaimExclusiveLock();
  966. //
  967. // We walk the active list of heaps and
  968. // delete everything.
  969. //
  970. for
  971. (
  972. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First());
  973. Current != NULL;
  974. Current = ((PRIVATE_HEAP*) ActiveHeaps -> First())
  975. )
  976. {
  977. //
  978. // Delete each heap from the active list,
  979. // call the destructor and delete any
  980. // associated space.
  981. //
  982. Current -> Delete( ActiveHeaps );
  983. #ifdef COMPLAIN_ABOUT_SMP_HEAP_LEAKS
  984. //
  985. // We have finished with the private
  986. // heap so now is a good time to complain
  987. // about leaks.
  988. //
  989. Current -> Heap.HeapLeaks();
  990. #endif
  991. //
  992. // We have finished with the private
  993. // heap so delete it.
  994. //
  995. PLACEMENT_DELETE( Current,PRIVATE_HEAP );
  996. SMP_HEAP_TYPE::Delete( Current );
  997. }
  998. //
  999. // We walk the free list of heaps and
  1000. // delete everything.
  1001. //
  1002. for
  1003. (
  1004. Current = ((PRIVATE_HEAP*) FreeHeaps -> First());
  1005. Current != NULL;
  1006. Current = ((PRIVATE_HEAP*) FreeHeaps -> First())
  1007. )
  1008. {
  1009. //
  1010. // Delete each heap from the active list,
  1011. // call the destructor and delete any
  1012. // associated space.
  1013. //
  1014. Current -> Delete( FreeHeaps );
  1015. #ifdef COMPLAIN_ABOUT_SMP_HEAP_LEAKS
  1016. //
  1017. // We have finished with the private
  1018. // heap so now is a good time to complain
  1019. // about leaks.
  1020. //
  1021. Current -> Heap.HeapLeaks();
  1022. #endif
  1023. //
  1024. // We have finished with the private
  1025. // heap so delete it.
  1026. //
  1027. PLACEMENT_DELETE( Current,PRIVATE_HEAP );
  1028. SMP_HEAP_TYPE::Delete( Current );
  1029. }
  1030. //
  1031. // Release the lock.
  1032. //
  1033. Sharelock.ReleaseExclusiveLock();
  1034. //
  1035. // Call the list and TLS destructors.
  1036. //
  1037. PLACEMENT_DELETE( Tls,TLS );
  1038. PLACEMENT_DELETE( FreeHeaps,LIST );
  1039. #ifdef COMPILING_ROCKALL_DLL
  1040. PLACEMENT_DELETE( DllEvents,DLL );
  1041. #endif
  1042. PLACEMENT_DELETE( ActiveHeaps,LIST );
  1043. //
  1044. // Delete the space.
  1045. //
  1046. SMP_HEAP_TYPE::Delete( Tls );
  1047. SMP_HEAP_TYPE::Delete( FreeHeaps );
  1048. SMP_HEAP_TYPE::Delete( DllEvents );
  1049. SMP_HEAP_TYPE::Delete( ActiveHeaps );
  1050. //
  1051. // Zero the pointers just to be tidy.
  1052. //
  1053. Tls = NULL;
  1054. HeapWalk = NULL;
  1055. FreeHeaps = NULL;
  1056. DllEvents = NULL;
  1057. ActiveHeaps = NULL;
  1058. }
  1059. }