/* $Id: heapshared.cpp,v 1.11 2003-01-13 16:51:39 sandervl Exp $ */ /* * Shared heap functions for OS/2 * * Initially commit 16 kb, add more when required * * NOTE: Hardcoded limit of 512 KB (increase when required) * * TODO: Not process/thread safe (initializing/destroying heap) * * ASSUMPTION: Rtl library takes care of protection of heap increase/decrease * (from multiple threads/processes) * * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl) * */ #define INCL_BASE #define INCL_DOSMEMMGR #define INCL_DOSPROCESS #include #include #include #include #include #include #include "initterm.h" #define DBG_LOCALLOG DBG_heapshared #include "dbglocal.h" // // Global constants (keep it in sync with globaldata.asm!) // #define PAGE_SIZE 4096 #define MAX_HEAPSIZE (8*1024*1024) #define MAX_HEAPPAGES (MAX_HEAPSIZE/PAGE_SIZE) #define INCR_HEAPSIZE (16*1024) // // Global DLL Data (keep it in sync with globaldata.asm!) // extern Heap_t sharedHeap; // = 0 extern PVOID pSharedMem; // = NULL extern BYTE pageBitmap[MAX_HEAPPAGES]; // = {0} extern ULONG refCount; // = 0; static int privateRefCount = 0; void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean); void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size); //****************************************************************************** //****************************************************************************** BOOL SYSTEM InitializeSharedHeap() { APIRET rc; ULONG flAllocMem = 0, ulSysinfo; //necessary until next WGSS update if(++privateRefCount > 1) { return TRUE; } rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo)); if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB { flAllocMem = PAG_ANY; } if(pSharedMem == NULL) { rc = DosAllocSharedMem(&pSharedMem, NULL, MAX_HEAPSIZE, PAG_READ|PAG_WRITE|OBJ_GETTABLE|flAllocMem); if(rc != 0) { dprintf(("InitializeSharedHeap: DosAllocSharedMem failed with %d", rc)); return FALSE; } rc = DosSetMem(pSharedMem, INCR_HEAPSIZE, PAG_READ|PAG_WRITE|PAG_COMMIT); if(rc != 0) { DosFreeMem(pSharedMem); dprintf(("InitializeSharedHeap: DosSetMem failed with %d", rc)); return FALSE; } sharedHeap = _ucreate(pSharedMem, INCR_HEAPSIZE, _BLOCK_CLEAN, _HEAP_REGULAR|_HEAP_SHARED, getmoreShared, releaseShared); if(sharedHeap == NULL) { DosFreeMem(pSharedMem); dprintf(("InitializeSharedHeap: _ucreate failed!")); return FALSE; } dprintf(("KERNEL32: First InitializeSharedHeap %x %x", pSharedMem, sharedHeap)); for(int i=0;i 0) { return; } #ifdef DEBUG _uheap_walk(sharedHeap, callback_function); dprintf((NULL)); #endif if(--refCount == 0) { if(sharedHeap) { _uclose(sharedHeap); _udestroy(sharedHeap, _FORCE); sharedHeap = NULL; } if(pSharedMem) { DosFreeMem(pSharedMem); pSharedMem = NULL; } } else { _uclose(sharedHeap); } } //****************************************************************************** //****************************************************************************** ULONG GetPageRangeFree(ULONG pageoffset) { dprintf(("KERNEL32: GetPageRangeFree(%08xh)", pageoffset)); int i; for(i=pageoffset;i= *size/PAGE_SIZE) { newblock = (PVOID)((ULONG)pSharedMem + i*PAGE_SIZE); rc = DosSetMem(newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT); if(rc != 0) { dprintf(("getmoreShared: DosSetMem failed with %d", rc)); return NULL; } for(int j=0;j < *size/PAGE_SIZE; j++) { pageBitmap[i+j] = 1; //mark as committed } *clean = _BLOCK_CLEAN; dprintf(("KERNEL32: getmoreShared %x %d", newblock, *size)); return newblock; } if(nrpagesfree) i += nrpagesfree-1; } dprintf(("KERNEL32: getmoreShared NOTHING LEFT (%d)", *size)); return NULL; } //****************************************************************************** //****************************************************************************** void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size) { ULONG pagenr; dprintf(("KERNEL32: releaseShared %x %d", block, size)); DosSetMem(block, size, PAG_READ|PAG_WRITE|PAG_DECOMMIT); pagenr = (ULONG)block - (ULONG)pSharedMem; pagenr /= PAGE_SIZE; for(int i=pagenr;i