Windows CE Memory Management Virtual Memory Simplicity Efficient use of physical memory Code and Data share-ability Protection But CE shares the address space between processes (not really switching them)
Use of 32-bit Addressing FFFF FFFF Process Slots Reserved for OS (on ROM?) 32 31 8000 0000 Memory-mapped Files 4200 0000 1 0000 0000
Each process gets a 32 MB slot But CE supports only 32 processes max Remember processes typically need for VA 0 to some value. This implies that a process needs to be copied to slot 0 before it can run Context switch will swap back from slot 0 to appropriate slot.
Process Address Space (32MB) DLLs Extra Heaps & Stacks Heap Primary Stack Data Code Reserved area (64K)
There is not really extensive protection between processes. A process can read and rite another process’ memory by calling ReadProcessMemory() and WriteProcessMemory(). Question: Why cannot a process directly read/write someone else’s memory?
Paging CE implements VM via paging Page sizes can be either 1KB or 4KB (depends on CPU) On a x86, Page Dir. Page Table 10 bits 12 bits Offset Frame #
Memory Allocation Stacks Heaps Default size is 58KB Can use malloc()/free() Can use HeapAlloc()/HeapFree() Can use VirtualAlloc()/VirtualFree()
Local Heap Each process has a default local heap Of 384 KB, and can grow based on requirements You can allocate/de-allocate from local heap using LocalAlloc/LocalFree Ptr = (void *) LocalAlloc(LPTR, size); ….. LocalFree((HLOCAL) Ptr);
Supplemental Heaps With just 1 heap, fragmentation problems can become prevalent with multiple allocation sizes. You may want to create multiple heap sizes, each operating for one small range of sizes.
Using supplemental heaps HANDLE Hp = HeapCreate(0, // No special flag size, // Initial size 0); // No max size in CE Ptr = (void *) HeapAlloc(Hp, // Heap to allocate from HEAP_ZERO_MEMORY, // Zero it out size); ……. HeapFree(Hp, 0, Ptr); GetProcessHeap() returns handle to Local Heap
Page Allocation Can directly call VirtualAlloc()/VirtualFree() provided by CE for page level management. These are anyway used by HeapAlloc/HeapFree (which are in turn used in implementing malloc/free). You can reserve a group of contiguous pages (without actually allocating physical memory), or you can also commit the physical memory at the same time. Usually, you auto-commit, i.e. you reserve and physical memory is allocated when you actually use this space
VirtualAlloc() pMemPool = VirtualAlloc(NULL, POOL_SIZE, MEM_RESERVE | MEM_AUTO_COMMIT. // Can also be MEM_COMMIT PAGE_READWRITE); // Permissions ….. UncommitMemory(pMemPool,MEM_POOL_SIZE); // Has to be uncommitted before freeing! VirtualFree(pMemPool, 0, MEM_RELEASE);
Uncommiting Memory UncommitMemory(LPVOID paddr, DWORD dwsize) { MaxAddr = paddr + dwsize; do { MEMORY_BASIC_INFORMATION mbi; VirtualQuery(paddr, &mbi, sizeof(mbi)); if (mbi.State & MEM_COMMIT) VirtualFree(mbi.BaseAddress, mbi.RegionSize, MEM_DECOMMIT); paddr = mbi.BaseAddress + mbi.RegionSize; } while (paddr < pMaxAddr); }
Relationship Application Globals VirtualAlloc() LocalAlloc() HeapAlloc() Malloc()/new() Stack
Thread Local Storage Having globals creates problems, either in application programs or in DLLs The variables are not actually shared! But at the same time using different names is inconvenient. CE provides declarations for TLBs. E.g. __declspec(thread) static int count; // Each thread has one such count
Memory Shortage It enters low memory state when available memory falls below threshold (128KB) It sends WM_HIBERNATE signal to applns asking them to release memory, and sends WM_ACTIVATE afterwards The memory allocation functions may start failing.
Static Memory Usage dumpbin /headers appln.exe Dumps the virtual addresses and sizes of different sections of the program. The common sections include .text (executable code) .data (global/static variables) .rdata (read-only data – strings, constants) .debug (debug information) You can try to go over the static layout, move things around to lower memory needs.
Dynamic Memory Usage GlobalMemoryStatus() returns VM and PM usage info using MEMORYSTATUS structure. Important fields of this structure dwMemoryLoad (util, in %) dwTotalPhys (total PM size) dwAvailPhys (Available PM size for system) dwTotalVirtual (total VM size) dwAvailVirtual (available VM size for process)
Remote Heap Walker This CE utility shows all the heaps used by an executing process For each heap, you can get what is allocated and what is free (and their addresses)
CESH Utility You can run “mi full” It gives for every process, for each page whether it is C (Code in ROM), R (read-only in ROM), c (Code in RAM), W (read-write in RAM), r (read-only in RAM), S (stack), O (Object store), P (pending commit), - (reserved, ready for commitment)
Optimizing for Low Memory Look at static and dynamic info for any possible optimizations Move as much data into read-only section (CE discards this more readily than read-write) Load data files only only when needed and write back as soon as possible. Process the WM_HIBERNATE message Track and fix memory leaks.