Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

965 lines
23 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: Mem.CXX
  7. //
  8. // Contents: Memory tracking code
  9. //
  10. // Classes: CMemAlloc
  11. //
  12. // Functions: DfCreateSharedAllocator
  13. // DfPrintAllocs
  14. // DfGetMemAlloced
  15. //
  16. // History: 17-May-93 AlexT Created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include <dfhead.cxx>
  20. #pragma hdrstop
  21. #if defined(WIN32)
  22. #include <smalloc.hxx>
  23. #include <olesem.hxx>
  24. #include <utils.hxx>
  25. // This global variable holds the base address of the shared memory region.
  26. // It is required by the based pointer stuff and is accessed directly.
  27. // Initialization is a side effect of calling DfCreateSharedAllocator or
  28. // DfSyncSharedMemory
  29. #ifdef MULTIHEAP
  30. //__declspec(thread) void *DFBASEPTR = NULL;
  31. #else
  32. void *DFBASEPTR = NULL;
  33. #endif
  34. #endif
  35. #if DBG == 1
  36. #include <dfdeb.hxx>
  37. #ifdef MEMTRACK
  38. #ifdef WIN32
  39. // Multithread protection for allocation list
  40. CStaticDfMutex _sdmtxAllocs(TSTR("DfAllocList"));
  41. #define TAKE_ALLOCS_MUTEX olVerSucc(_sdmtxAllocs.Take(INFINITE))
  42. #define RELEASE_ALLOCS_MUTEX _sdmtxAllocs.Release()
  43. #else
  44. #define TAKE_ALLOCS_MUTEX
  45. #define RELEASE_ALLOCS_MUTEX
  46. #endif
  47. #define GET_ALLOC_LIST_HEAD ((CMemAlloc *)DfGetResLimit(DBRI_ALLOC_LIST))
  48. #define SET_ALLOC_LIST_HEAD(pma) DfSetResLimit(DBRI_ALLOC_LIST, (LONG)(pma))
  49. #endif // MEMTRACK
  50. #define DEB_MEMORY 0x01000000
  51. #define DEB_LEAKS 0x01100000
  52. const int NEWMEM = 0xDEDE;
  53. const int OLDMEM = 0xEDED;
  54. //+--------------------------------------------------------------
  55. //
  56. // Class: CMemAlloc (ma)
  57. //
  58. // Purpose: Tracks memory allocations
  59. //
  60. // Interface: See below
  61. //
  62. // History: 08-Jul-92 DrewB Created
  63. // 17-May-93 AlexT Add idContext
  64. //
  65. //---------------------------------------------------------------
  66. class CMemAlloc
  67. {
  68. public:
  69. void *pvCaller;
  70. void *pvMem;
  71. ULONG cbSize;
  72. ContextId idContext;
  73. #ifdef MEMTRACK
  74. CMemAlloc *pmaPrev, *pmaNext;
  75. #endif
  76. };
  77. //+---------------------------------------------------------------------------
  78. //
  79. // Function: AddAlloc, private
  80. //
  81. // Synopsis: Puts an allocation into the allocation list
  82. //
  83. // Arguments: [pma] - Allocation descriptor
  84. // [pvCaller] - Allocator
  85. // [cbSize] - Real size
  86. // [pvMem] - Memory block
  87. // [cid] - Context ID
  88. //
  89. // History: 11-Jan-94 DrewB Created
  90. //
  91. //----------------------------------------------------------------------------
  92. #if DBG == 1
  93. static void AddAlloc(CMemAlloc *pma, void *pvCaller, ULONG cbSize,
  94. void *pvMem, ContextId cid)
  95. {
  96. pma->pvCaller = pvCaller;
  97. pma->cbSize = cbSize;
  98. pma->pvMem = pvMem;
  99. pma->idContext = cid;
  100. #ifdef MEMTRACK
  101. TAKE_ALLOCS_MUTEX;
  102. pma->pmaNext = GET_ALLOC_LIST_HEAD;
  103. if (pma->pmaNext)
  104. pma->pmaNext->pmaPrev = pma;
  105. pma->pmaPrev = NULL;
  106. olAssert(!IsBadReadPtr(pma, sizeof(CMemAlloc)));
  107. SET_ALLOC_LIST_HEAD(pma);
  108. RELEASE_ALLOCS_MUTEX;
  109. ModifyResLimit(DBRQ_MEMORY_ALLOCATED, (LONG)cbSize);
  110. olDebugOut((DEB_MEMORY, "%s alloced %p:%lu, total %ld\n",
  111. cid != 0 ? "Task" : "Shrd",
  112. pvMem, pma->cbSize, DfGetResLimit(DBRQ_MEMORY_ALLOCATED)));
  113. #endif
  114. }
  115. #endif
  116. //+---------------------------------------------------------------------------
  117. //
  118. // Function: RemoveAlloc, private
  119. //
  120. // Synopsis: Takes an allocation out of the allocation list
  121. //
  122. // Arguments: [pma] - Allocation descriptor
  123. // [pvMem] - Real allocation
  124. // [cid] - Context ID
  125. //
  126. // History: 11-Jan-94 DrewB Created
  127. //
  128. //----------------------------------------------------------------------------
  129. #if DBG == 1
  130. static void RemoveAlloc(CMemAlloc *pma, void *pvMem, ContextId cid)
  131. {
  132. #ifdef MEMTRACK
  133. olAssert(pma->pvMem == pvMem && aMsg("Address mismatch"));
  134. olAssert(pma->idContext == cid && aMsg("Context mismatch"));
  135. TAKE_ALLOCS_MUTEX;
  136. olAssert(pma->pmaNext == NULL ||
  137. !IsBadReadPtr(pma->pmaNext, sizeof(CMemAlloc)));
  138. olAssert(pma->pmaPrev == NULL ||
  139. !IsBadReadPtr(pma->pmaPrev, sizeof(CMemAlloc)));
  140. if (pma->pmaPrev)
  141. {
  142. pma->pmaPrev->pmaNext = pma->pmaNext;
  143. }
  144. else
  145. {
  146. SET_ALLOC_LIST_HEAD(pma->pmaNext);
  147. }
  148. if (pma->pmaNext)
  149. {
  150. pma->pmaNext->pmaPrev = pma->pmaPrev;
  151. }
  152. RELEASE_ALLOCS_MUTEX;
  153. ModifyResLimit(DBR_MEMORY, (LONG)pma->cbSize);
  154. ModifyResLimit(DBRQ_MEMORY_ALLOCATED, -(LONG)pma->cbSize);
  155. olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
  156. olDebugOut((DEB_MEMORY, "%s freed %p:%lu, total %ld\n",
  157. cid != 0 ? "Task" : "Shrd",
  158. pma->pvMem, pma->cbSize,
  159. DfGetResLimit(DBRQ_MEMORY_ALLOCATED)));
  160. #endif
  161. }
  162. #endif
  163. //+---------------------------------------------------------------------------
  164. //
  165. // Function: DfGetMemAlloced, private
  166. //
  167. // Synopsis: Returns the amount of memory currently allocated
  168. //
  169. // History: 08-Jul-92 DrewB Created
  170. //
  171. //----------------------------------------------------------------------------
  172. STDAPI_(LONG) DfGetMemAlloced(void)
  173. {
  174. return DfGetResLimit(DBRQ_MEMORY_ALLOCATED);
  175. }
  176. //+--------------------------------------------------------------
  177. //
  178. // Function: DfPrintAllocs, private
  179. //
  180. // Synopsis: Walks the allocation list and prints out their info
  181. //
  182. // History: 08-Jul-92 DrewB Created
  183. //
  184. //---------------------------------------------------------------
  185. STDAPI_(void) DfPrintAllocs(void)
  186. {
  187. #ifdef MEMTRACK
  188. CMemAlloc *pma;
  189. olDebugOut((DEB_ITRACE, "In DfPrintAllocs()\n"));
  190. TAKE_ALLOCS_MUTEX;
  191. pma = GET_ALLOC_LIST_HEAD;
  192. while (pma != NULL)
  193. {
  194. olDebugOut((DEB_LEAKS, "Alloc %s: %p alloc %p:%4lu bytes\n",
  195. pma->idContext ? "LOCAL" : "SHARED",
  196. pma->pvCaller, pma->pvMem, pma->cbSize));
  197. pma = pma->pmaNext;
  198. }
  199. RELEASE_ALLOCS_MUTEX;
  200. olDebugOut((DEB_ITRACE, "Out DfPrintAllocs\n"));
  201. #endif
  202. }
  203. #endif
  204. #ifdef MULTIHEAP
  205. CSmAllocator g_SmAllocator; // optimization for single threaded case
  206. CErrorSmAllocator g_ErrorSmAllocator;
  207. IMalloc *g_pTaskAllocator = 0;
  208. CSharedMemoryBlock g_smb; // optimize single threaded case
  209. ULONG g_ulHeapName = 0; // name of the above heap
  210. TEB * g_pteb = NtCurrentTeb();
  211. CSmAllocator& GetTlsSmAllocator()
  212. {
  213. HRESULT hr;
  214. COleTls otls(hr); // even for main thread, we need to initialize TLS
  215. memAssert (SUCCEEDED(hr) && "Error initializing TLS");
  216. if (g_pteb == NtCurrentTeb())
  217. {
  218. // return the static global allocator for main thread
  219. // DoThreadSpecificCleanup does not deallocate this allocator
  220. return g_SmAllocator;
  221. }
  222. if (otls->pSmAllocator == NULL)
  223. {
  224. if ((otls->pSmAllocator = new CSmAllocator()) == NULL)
  225. otls->pSmAllocator = &g_ErrorSmAllocator;
  226. // DoThreadSpecificCleanup will deallocate this when thread goes away
  227. }
  228. return *(otls->pSmAllocator);
  229. }
  230. //
  231. // This initialization used to be done in the global allocator
  232. // which is now a per thread allocator
  233. //
  234. class CResourceCriticalSection
  235. {
  236. public:
  237. CResourceCriticalSection ()
  238. {
  239. #if WIN32 == 100
  240. _nts = RtlInitializeCriticalSection(&g_csScratchBuffer);
  241. #else
  242. InitializeCriticalSection(&g_csScratchBuffer);
  243. #endif
  244. }
  245. ~CResourceCriticalSection ()
  246. {
  247. #if WIN32 == 100
  248. if (NT_SUCCESS(_nts))
  249. #endif
  250. DeleteCriticalSection(&g_csScratchBuffer);
  251. }
  252. #if WIN32 == 100
  253. HRESULT GetInitializationError ()
  254. {
  255. return NtStatusToScode(_nts);
  256. }
  257. private:
  258. NTSTATUS _nts;
  259. #endif
  260. };
  261. CResourceCriticalSection g_ResourceCriticalSection;
  262. #else
  263. CSmAllocator g_smAllocator;
  264. #endif // MULTIHEAP
  265. //+-------------------------------------------------------------------------
  266. //
  267. // Member: CMallocBased::operator new, public
  268. //
  269. // Synopsis: Overridden allocator
  270. //
  271. // Effects: Allocates memory from given allocator
  272. //
  273. // Arguments: [size] -- byte count to allocate
  274. // [pMalloc] -- allocator
  275. //
  276. // Returns: memory block address
  277. //
  278. // Algorithm:
  279. //
  280. // History: 21-May-93 AlexT Created
  281. //
  282. // Notes:
  283. //
  284. //--------------------------------------------------------------------------
  285. void *CMallocBased::operator new(size_t size, IMalloc * const pMalloc)
  286. {
  287. #ifndef WIN32
  288. olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
  289. #endif
  290. olAssert(size > 0);
  291. #if DBG==1
  292. if (SimulateFailure(DBF_MEMORY))
  293. {
  294. return(NULL);
  295. }
  296. if (!HaveResource(DBR_MEMORY, (LONG)size))
  297. {
  298. // Artificial limit exceeded so force failure
  299. return NULL;
  300. }
  301. #endif
  302. void *pv = g_smAllocator.Alloc(
  303. #if DBG==1
  304. sizeof(CMemAlloc) +
  305. #endif
  306. size);
  307. if (pv == NULL)
  308. {
  309. #if DBG==1
  310. ModifyResLimit(DBR_MEMORY, (LONG)size);
  311. #endif
  312. return NULL;
  313. }
  314. #if DBG==1
  315. memset(pv, NEWMEM, sizeof(CMemAlloc) + size);
  316. #endif
  317. #if DBG==1
  318. // Put debug info in buffer
  319. // Note: This assumes CMemAlloc will end up properly aligned
  320. CMemAlloc *pma = (CMemAlloc *) pv;
  321. pv = (void *) ((CMemAlloc *) pv + 1);
  322. #if defined(_X86_)
  323. PVOID ra = *(((void **)&size)-1);
  324. #else
  325. PVOID ra = _ReturnAddress();
  326. #endif
  327. AddAlloc(pma, ra, size, pv, 0);
  328. #endif
  329. return pv;
  330. }
  331. //+-------------------------------------------------------------------------
  332. //
  333. // Member: CMallocBased::operator delete
  334. //
  335. // Synopsis: Overridden deallocator
  336. //
  337. // Effects: Frees memory block
  338. //
  339. // Arguments: [pv] -- memory block address
  340. //
  341. // Algorithm:
  342. //
  343. // History: 21-May-93 AlexT Created
  344. //
  345. // Notes:
  346. //
  347. //--------------------------------------------------------------------------
  348. void CMallocBased::operator delete(void *pv)
  349. {
  350. if (pv == NULL)
  351. return;
  352. #if DBG==1
  353. // Assumes ma ends up properly aligned
  354. CMemAlloc *pma = (CMemAlloc *) pv;
  355. pma--;
  356. RemoveAlloc(pma, pv, 0);
  357. pv = (void *) pma;
  358. memset(pv, OLDMEM, (size_t) pma->cbSize);
  359. #endif
  360. g_smAllocator.Free(pv);
  361. }
  362. //+-------------------------------------------------------------------------
  363. //
  364. // Member: CMallocBased::deleteNoMutex
  365. //
  366. // Synopsis: deallocator function without Mutex
  367. //
  368. // Effects: Frees memory block
  369. //
  370. // Arguments: [pv] -- memory block address
  371. // Algorithm:
  372. //
  373. // History: 19-Jul-95 SusiA Created
  374. //
  375. // Notes:
  376. //
  377. //--------------------------------------------------------------------------
  378. void CMallocBased::deleteNoMutex(void *pv)
  379. {
  380. if (pv == NULL)
  381. return;
  382. #if DBG==1
  383. // Assumes ma ends up properly aligned
  384. CMemAlloc *pma = (CMemAlloc *) pv;
  385. pma--;
  386. RemoveAlloc(pma, pv, 0);
  387. pv = (void *) pma;
  388. memset(pv, OLDMEM, (size_t) pma->cbSize);
  389. #endif
  390. g_smAllocator.FreeNoMutex(pv);
  391. }
  392. #if !defined(WIN32) && DBG==1
  393. //+-------------------------------------------------------------------------
  394. //
  395. // Class: CSharedMalloc
  396. //
  397. // Purpose: Track shared allocators
  398. //
  399. // Interface: IMalloc
  400. //
  401. // History: 28-May-93 AlexT Created
  402. //
  403. // Notes: This is only for builds that use CoCreateStandardMalloc
  404. // (which is non-WIN32 builds for now). We inherit from
  405. // CMallocBased to pick up memory tracking.
  406. //
  407. //--------------------------------------------------------------------------
  408. class CSharedMalloc : public IMalloc, public CMallocBased
  409. {
  410. public:
  411. CSharedMalloc(IMalloc *pMalloc);
  412. // *** IUnknown methods ***
  413. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  414. STDMETHOD_(ULONG,AddRef) (THIS);
  415. STDMETHOD_(ULONG,Release) (THIS);
  416. // *** IMalloc methods ***
  417. STDMETHOD_(void FAR*, Alloc) (THIS_ SIZE_T cb);
  418. STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, SIZE_T cb);
  419. STDMETHOD_(void, Free) (THIS_ void FAR* pv);
  420. STDMETHOD_(SIZE_T, GetSize) (THIS_ void FAR* pv);
  421. STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv);
  422. STDMETHOD_(void, HeapMinimize) (THIS);
  423. private:
  424. IMalloc * const _pMalloc;
  425. };
  426. CSharedMalloc::CSharedMalloc(IMalloc *pMalloc)
  427. : _pMalloc(pMalloc)
  428. {
  429. _pMalloc->AddRef();
  430. }
  431. STDMETHODIMP CSharedMalloc::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj)
  432. {
  433. olAssert(!aMsg("CSharedMalloc::QueryInterface unsupported"));
  434. return(ResultFromScode(E_UNEXPECTED));
  435. }
  436. STDMETHODIMP_(ULONG) CSharedMalloc::AddRef (THIS)
  437. {
  438. return(_pMalloc->AddRef());
  439. }
  440. STDMETHODIMP_(ULONG) CSharedMalloc::Release (THIS)
  441. {
  442. ULONG cRef = _pMalloc->Release();
  443. if (cRef == 0)
  444. delete this;
  445. return (ULONG) cRef;
  446. }
  447. STDMETHODIMP_(void FAR*) CSharedMalloc::Alloc (THIS_ SIZE_T cb)
  448. {
  449. return _pMalloc->Alloc(cb);
  450. }
  451. STDMETHODIMP_(void FAR*) CSharedMalloc::Realloc (THIS_ void FAR* pv, SIZE_T cb)
  452. {
  453. olAssert(!aMsg("CSharedMalloc::Realloc unsupported"));
  454. return(NULL);
  455. }
  456. STDMETHODIMP_(void) CSharedMalloc::Free (THIS_ void FAR* pv)
  457. {
  458. _pMalloc->Free(pv);
  459. }
  460. STDMETHODIMP_(SIZE_T) CSharedMalloc::GetSize (THIS_ void FAR* pv)
  461. {
  462. olAssert(!aMsg("CSharedMalloc::GetSize unsupported"));
  463. return(0);
  464. }
  465. STDMETHODIMP_(int) CSharedMalloc::DidAlloc (THIS_ void FAR* pv)
  466. {
  467. olAssert(!aMsg("CSharedMalloc::DidAlloc unsupported"));
  468. return(TRUE);
  469. }
  470. STDMETHODIMP_(void) CSharedMalloc::HeapMinimize (THIS)
  471. {
  472. olAssert(!aMsg("CSharedMalloc::HeapMinimize unsupported"));
  473. }
  474. #endif
  475. #if !defined(MULTIHEAP)
  476. COleStaticMutexSem mxsInitSm;
  477. BOOL fInitialisedSm = FALSE;
  478. //+-------------------------------------------------------------------------
  479. //
  480. // Function: DfCreateSharedAllocator
  481. //
  482. // Synopsis: Initialises the shared memory region for this process.
  483. //
  484. // Arguments: [ppm] -- return address for shared memory IMalloc*
  485. //
  486. // Returns: status code
  487. //
  488. // History: 27-May-94 MikeSe Created
  489. //
  490. // Notes: This routine is called indirectly through DfCreateSharedAllocator, in
  491. // such a way that in most circumstances it will be executed
  492. // exactly once per process. (Because we overwrite the contents
  493. // of DfCreateSharedAllocator if successful).
  494. //
  495. // However, in order to be multi-thread safe, we need a process
  496. // mutex to prevent execution of the initialisation code twice.
  497. //
  498. // Furthermore, since we are initialising system-wide state
  499. // (namely the shared memory region) we must provide cross-process
  500. // mutual exclusion over this activity.
  501. //
  502. //--------------------------------------------------------------------------
  503. HRESULT DfCreateSharedAllocator (IMalloc ** ppm, BOOL fTaskMemory )
  504. {
  505. // multi-thread safety
  506. mxsInitSm.Request();
  507. HRESULT hr = S_OK;
  508. if ( !fInitialisedSm )
  509. {
  510. // We need to do the initialisation. Obtain exclusion against
  511. // other processes.
  512. SECURITY_ATTRIBUTES secattr;
  513. secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
  514. #ifndef _CHICAGO_
  515. CWorldSecurityDescriptor wsd;
  516. secattr.lpSecurityDescriptor = &wsd;
  517. #else
  518. secattr.lpSecurityDescriptor = NULL;
  519. #endif // !_CHICAGO_
  520. secattr.bInheritHandle = FALSE;
  521. HANDLE hMutex = CreateMutex ( &secattr, FALSE, TEXT("OleDfSharedMemoryMutex"));
  522. if ( hMutex == NULL && GetLastError() == ERROR_ACCESS_DENIED )
  523. hMutex = OpenMutex(SYNCHRONIZE, FALSE, TEXT("OleDfSharedMemoryMutex"));
  524. if ( hMutex != NULL )
  525. {
  526. WaitForSingleObject ( hMutex, INFINITE );
  527. hr = g_smAllocator.Init ( DOCFILE_SM_NAME );
  528. if ( SUCCEEDED(hr) )
  529. {
  530. *ppm = &g_smAllocator;
  531. // Also set up base address
  532. #ifdef USEBASED
  533. DFBASEPTR = g_smAllocator.GetBase();
  534. #endif
  535. fInitialisedSm = TRUE;
  536. }
  537. ReleaseMutex ( hMutex );
  538. }
  539. else
  540. hr = HRESULT_FROM_WIN32(GetLastError());
  541. }
  542. else // fInitialisedSm is TRUE
  543. {
  544. *ppm = &g_smAllocator;
  545. }
  546. mxsInitSm.Release();
  547. return hr;
  548. }
  549. #endif // !defined(MULTIHEAP)
  550. #ifdef MULTIHEAP
  551. //+-------------------------------------------------------------------------
  552. //
  553. // Function: DfCreateSharedAllocator
  554. //
  555. // Synopsis: Initialises a shared memory region for this process.
  556. //
  557. // Arguments: [ppm] -- return address for shared memory IMalloc*
  558. //
  559. // Returns: status code
  560. //
  561. // History: 20-Nov-95 HenryLee Created
  562. //
  563. // Notes: This routine is called indirectly by DfCreateSharedAllocator
  564. // such a way that in most circumstances it will be executed
  565. // exactly once per docfile open.
  566. //
  567. //--------------------------------------------------------------------------
  568. HRESULT DfCreateSharedAllocator (IMalloc ** ppm, BOOL fTaskMemory )
  569. {
  570. HRESULT hr = S_OK;
  571. #if WIN32 == 100
  572. hr = g_ResourceCriticalSection.GetInitializationError();
  573. if (!SUCCEEDED(hr))
  574. return hr;
  575. #endif
  576. CSmAllocator *pMalloc = &g_smAllocator;
  577. *ppm = NULL;
  578. if ((gs_iSharedHeaps > (DOCFILE_SM_LIMIT / DOCFILE_SM_SIZE)) ||
  579. fTaskMemory)
  580. {
  581. // use task allocator if we eat up 1Gig of address space
  582. if (g_pTaskAllocator == NULL)
  583. {
  584. hr = CoGetMalloc (MEMCTX_TASK, &g_pTaskAllocator);
  585. if (!SUCCEEDED(hr))
  586. return hr;
  587. }
  588. // reset the allocator state to initialize it properly
  589. pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
  590. DFBASEPTR = 0;
  591. *ppm = g_pTaskAllocator;
  592. }
  593. else
  594. {
  595. LUID luid; // generate a unique name
  596. if (AllocateLocallyUniqueId (&luid) == FALSE)
  597. return HRESULT_FROM_WIN32(GetLastError());
  598. // reset the allocator state to initialize it properly
  599. pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
  600. hr = pMalloc->Init ( luid.LowPart, FALSE );
  601. if ( SUCCEEDED(hr) )
  602. {
  603. *ppm = pMalloc;
  604. DFBASEPTR = pMalloc->GetBase();
  605. pMalloc->AddRef();
  606. }
  607. }
  608. return hr;
  609. }
  610. #endif
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Function: DfSyncSharedMemory, public
  614. //
  615. // Synopsis: Sync up shared memory
  616. //
  617. // Returns: Appropriate status code
  618. //
  619. // History: 08-Apr-94 PhilipLa Created
  620. //
  621. // Notes:
  622. //
  623. //----------------------------------------------------------------------------
  624. #ifdef MULTIHEAP
  625. SCODE DfSyncSharedMemory(ULONG ulHeapName)
  626. #else
  627. SCODE DfSyncSharedMemory(void)
  628. #endif
  629. {
  630. // make sure we have initialised
  631. HRESULT hr = S_OK;
  632. #ifdef MULTIHEAP
  633. CSmAllocator *pMalloc = &g_smAllocator;
  634. if (ulHeapName != 0) // reopen a shared heap for unmarshaling
  635. {
  636. // reset the allocator state to initialize it properly
  637. pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
  638. hr = pMalloc->Init ( ulHeapName, TRUE);
  639. DFBASEPTR = pMalloc->GetBase();
  640. }
  641. else // try to create a new shared heap
  642. #else
  643. if (!fInitialisedSm)
  644. #endif // MULTIHEAP
  645. {
  646. IMalloc * pm;
  647. hr = DfCreateSharedAllocator ( &pm, FALSE );
  648. }
  649. if ( SUCCEEDED(hr) )
  650. #ifdef MULTIHEAP
  651. hr = pMalloc->Sync();
  652. #else
  653. hr = g_smAllocator.Sync();
  654. #endif
  655. return hr;
  656. }
  657. //+---------------------------------------------------------------------------
  658. //
  659. // Function: DfInitSharedMemBase, public
  660. //
  661. // Synopsis: Set up the base of shared memory
  662. //
  663. // History: 31-May-94 MikeSe Created
  664. //
  665. // Notes:
  666. //
  667. //----------------------------------------------------------------------------
  668. void DfInitSharedMemBase()
  669. {
  670. #if !defined MULTIHEAP
  671. // make sure we have initialised. This is sufficient to ensure
  672. // that DFBASEPTR is set up
  673. if (!fInitialisedSm)
  674. {
  675. IMalloc * pm;
  676. HRESULT hr = DfCreateSharedAllocator ( &pm );
  677. }
  678. #endif
  679. }
  680. #if DBG==1 && !defined(MULTIHEAP)
  681. //+-------------------------------------------------------------------------
  682. //
  683. // Method: CLocalAlloc::operator new, public
  684. //
  685. // Synopsis: Overloaded new operator to allocate objects from
  686. // task local space.
  687. //
  688. // Arguments: [size] -- Size of block to allocate
  689. //
  690. // Returns: Pointer to memory allocated.
  691. //
  692. // History: 17-Aug-92 PhilipLa Created.
  693. // 18-May-93 AlexT Switch to task IMalloc
  694. //
  695. //--------------------------------------------------------------------------
  696. void *CLocalAlloc::operator new(size_t size)
  697. {
  698. #ifndef WIN32
  699. olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
  700. #endif
  701. olAssert(size > 0);
  702. if (SimulateFailure(DBF_MEMORY))
  703. {
  704. return(NULL);
  705. }
  706. if (!HaveResource(DBR_MEMORY, (LONG)size))
  707. {
  708. // Artificial limit exceeded so force failure
  709. return NULL;
  710. }
  711. void *pv = TaskMemAlloc(sizeof(CMemAlloc *) + size);
  712. if (pv != NULL)
  713. {
  714. void * const pvOrig = pv;
  715. memset(pv, NEWMEM, sizeof(CMemAlloc *) + size);
  716. CMemAlloc *pma = NULL;
  717. // Allocate tracking block (with shared memory)
  718. IMalloc *pMalloc;
  719. #ifdef WIN32
  720. #ifdef MULTIHEAP
  721. pMalloc = &g_smAllocator;
  722. #else
  723. if ( FAILED(DfCreateSharedAllocator ( &pMalloc )) )
  724. pMalloc = NULL;
  725. #endif // MULTIHEAP
  726. #else
  727. if (FAILED(DfGetScode(CoGetMalloc(MEMCTX_SHARED, &pMalloc))))
  728. pMalloc = NULL;
  729. #endif
  730. if (pMalloc)
  731. {
  732. pma = (CMemAlloc *) pMalloc->Alloc(sizeof(CMemAlloc));
  733. if (pma != NULL)
  734. {
  735. memset(pma, NEWMEM, sizeof(CMemAlloc));
  736. CMemAlloc **ppma = (CMemAlloc **) pv;
  737. pv = (void *) ((CMemAlloc **)pv + 1);
  738. *ppma = pma;
  739. AddAlloc(pma, *(((void **)&size)-1), size, pv,
  740. GetCurrentContextId());
  741. }
  742. pMalloc->Release();
  743. }
  744. if (pma == NULL)
  745. {
  746. // Couldn't allocate tracking block - fail allocation
  747. TaskMemFree(pvOrig);
  748. pv = NULL;
  749. }
  750. }
  751. if (pv == NULL)
  752. {
  753. ModifyResLimit(DBR_MEMORY, (LONG)size);
  754. }
  755. return(pv);
  756. }
  757. //+-------------------------------------------------------------------------
  758. //
  759. // Method: CLocalAlloc::operator delete, public
  760. //
  761. // Synopsis: Free memory from task local space
  762. //
  763. // Arguments: [pv] -- Pointer to memory to free
  764. //
  765. // History: 17-Aug-92 PhilipLa Created.
  766. // 18-May-93 AlexT Switch to task IMalloc
  767. //
  768. //--------------------------------------------------------------------------
  769. void CLocalAlloc::operator delete(void *pv)
  770. {
  771. if (pv == NULL)
  772. return;
  773. CMemAlloc **ppma = (CMemAlloc **)pv;
  774. ppma--;
  775. CMemAlloc *pma = *ppma;
  776. RemoveAlloc(pma, pv, GetCurrentContextId());
  777. pv = (void *) ppma;
  778. memset(pv, OLDMEM, (size_t) pma->cbSize);
  779. // Free tracking block
  780. IMalloc *pMalloc = NULL;
  781. #ifdef WIN32
  782. #ifdef MULTIHEAP
  783. pMalloc = &g_smAllocator;
  784. #else
  785. if ( FAILED(DfCreateSharedAllocator ( &pMalloc )) )
  786. pMalloc = NULL;
  787. #endif // MULTIHEAP
  788. #else
  789. if (FAILED(DfGetScode(CoGetMalloc(MEMCTX_SHARED, &pMalloc))))
  790. pMalloc = NULL;
  791. #endif
  792. if (pMalloc != NULL)
  793. {
  794. memset(pma, OLDMEM, sizeof(CMemAlloc));
  795. pMalloc->Free(pma);
  796. pMalloc->Release();
  797. }
  798. else
  799. olAssert(!aMsg("Unable to get shared allocator\n"));
  800. TaskMemFree(pv);
  801. }
  802. #endif // DBG==1 && !defined(MULTIHEAP)