|
|
1.1 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: ! 12: /****************************** Module Header ******************************* ! 13: * Module Name: GMEM.C ! 14: * ! 15: * Memory utility functions. ! 16: * ! 17: * Functions: ! 18: * ! 19: * gmem_panic() ! 20: * gmem_init() ! 21: * gmem_get() ! 22: * gmem_free() ! 23: * gmem_freeall() ! 24: * ! 25: * Comments: ! 26: * ! 27: * Global heap functions - allocate and free many small ! 28: * pieces of memory by calling global alloc for large pieces ! 29: * and breaking them up. A heap contains a critical section, so ! 30: * multiple simultaneous calls to gmem_get and gmem_free will be ! 31: * protected. ! 32: * ! 33: * gmem_freeall should not be called until all other users have finished ! 34: * with the heap. ! 35: * ! 36: * Out-of-memory is not something we regard as normal. ! 37: * If we cannot allocate memory - we put up an abort-retry-ignore ! 38: * error, and only return from the function if the user selects ignore. ! 39: * ! 40: ****************************************************************************/ ! 41: ! 42: #include <windows.h> ! 43: #include <memory.h> ! 44: ! 45: #include "gutils.h" ! 46: ! 47: int gmem_panic(void); ! 48: ! 49: ! 50: /* ensure BLKSIZE is multiple of sizeof(DWORD) */ ! 51: #define BLKSIZE 64 /* blk size in bytes */ ! 52: #define ALLOCSIZE 32768 ! 53: #define NBLKS (ALLOCSIZE / BLKSIZE) ! 54: #define MAPSIZE (NBLKS / 8) ! 55: #define MAPLONGS (MAPSIZE / sizeof(DWORD)) ! 56: #define TO_BLKS(x) (((x) + BLKSIZE - 1) / BLKSIZE) ! 57: ! 58: typedef struct seghdr { ! 59: HANDLE hseg; ! 60: CRITICAL_SECTION critsec; ! 61: struct seghdr FAR * pnext; ! 62: long nblocks; ! 63: DWORD segmap[MAPLONGS]; ! 64: } SEGHDR, FAR * SEGHDRP; ! 65: ! 66: ! 67: /* anything above this size, we alloc directly from global heap */ ! 68: #define MAXGALLOC 20000 ! 69: ! 70: ! 71: /*************************************************************************** ! 72: * Function: gmem_init ! 73: * ! 74: * Purpose: ! 75: * ! 76: * init heap - create first segment ! 77: */ ! 78: HANDLE APIENTRY ! 79: gmem_init(void) ! 80: { ! 81: HANDLE hNew; ! 82: SEGHDRP hp; ! 83: ! 84: /* retry all memory allocations after calling gmem_panic */ ! 85: do { ! 86: hNew = GlobalAlloc(GHND, ALLOCSIZE); ! 87: if (hNew == NULL) { ! 88: if (gmem_panic() == IDIGNORE) { ! 89: return(NULL); ! 90: } ! 91: } ! 92: } while (hNew == NULL); ! 93: ! 94: hp = (SEGHDRP) GlobalLock(hNew); ! 95: if (hp == NULL) { ! 96: return(NULL); ! 97: } ! 98: hp->hseg = hNew; ! 99: InitializeCriticalSection(&hp->critsec); ! 100: hp->pnext = NULL; ! 101: gbit_init(hp->segmap, NBLKS); ! 102: gbit_alloc(hp->segmap, 1, TO_BLKS(sizeof(SEGHDR))); ! 103: hp->nblocks = NBLKS - TO_BLKS(sizeof(SEGHDR)); ! 104: ! 105: return(hNew); ! 106: } ! 107: ! 108: /*************************************************************************** ! 109: * Function: gmem_get ! 110: * ! 111: * Purpose: ! 112: * ! 113: * Get memory from heap ! 114: */ ! 115: LPSTR APIENTRY ! 116: gmem_get(HANDLE hHeap, int len) ! 117: { ! 118: SEGHDRP chainp; ! 119: HANDLE hNew; ! 120: SEGHDRP hp; ! 121: LPSTR chp; ! 122: long nblks; ! 123: long start; ! 124: long nfound; ! 125: ! 126: ! 127: /* the heap is always locked (in gmem_init)- so having got the ! 128: * pointer, we can always safely unlock it ! 129: */ ! 130: chainp = (SEGHDRP) GlobalLock(hHeap); ! 131: GlobalUnlock(hHeap); ! 132: ! 133: if (len < 1) { ! 134: return(NULL); ! 135: } ! 136: ! 137: /* ! 138: * too big to be worth allocing from heap - get from globalalloc ! 139: */ ! 140: if (len > MAXGALLOC) { ! 141: /* retry all memory allocations after calling gmem_panic */ ! 142: do { ! 143: hNew = GlobalAlloc(GHND, len); ! 144: if (hNew == NULL) { ! 145: if (gmem_panic() == IDIGNORE) { ! 146: return(NULL); ! 147: } ! 148: } ! 149: } while (hNew == NULL); ! 150: ! 151: chp = GlobalLock(hNew); ! 152: if (chp == NULL) { ! 153: return(NULL); ! 154: } ! 155: return(chp); ! 156: } ! 157: ! 158: ! 159: /* ! 160: * get critical section during all access to the heap itself ! 161: */ ! 162: EnterCriticalSection(&chainp->critsec); ! 163: ! 164: nblks = TO_BLKS(len + sizeof(HANDLE)); ! 165: ! 166: for (hp = chainp; hp !=NULL; hp = hp->pnext) { ! 167: if (hp->nblocks >= nblks) { ! 168: nfound = gbit_findfree(hp->segmap, nblks,NBLKS, &start); ! 169: if (nfound >= nblks) { ! 170: gbit_alloc(hp->segmap, start, nblks); ! 171: hp->nblocks -= nblks; ! 172: ! 173: /* convert blocknr to pointer ! 174: * store seg handle in block ! 175: */ ! 176: chp = (LPSTR) hp; ! 177: chp = &chp[ (start-1) * BLKSIZE]; ! 178: * ( (HANDLE FAR *) chp) = hp->hseg; ! 179: chp += sizeof(HANDLE); ! 180: ! 181: break; ! 182: } ! 183: } ! 184: } ! 185: if (hp == NULL) { ! 186: /* retry all memory allocations after calling gmem_panic */ ! 187: do { ! 188: hNew = GlobalAlloc(GHND, ALLOCSIZE); ! 189: if (hNew == NULL) { ! 190: if (gmem_panic() == IDIGNORE) { ! 191: LeaveCriticalSection(&chainp->critsec); ! 192: return(NULL); ! 193: } ! 194: } ! 195: } while (hNew == NULL); ! 196: ! 197: hp = (SEGHDRP) GlobalLock(hNew); ! 198: if (hp == NULL) { ! 199: LeaveCriticalSection(&chainp->critsec); ! 200: return(NULL); ! 201: } ! 202: hp->pnext = chainp->pnext; ! 203: hp->hseg = hNew; ! 204: chainp->pnext = hp; ! 205: gbit_init(hp->segmap, NBLKS); ! 206: gbit_alloc(hp->segmap, 1, TO_BLKS(sizeof(SEGHDR))); ! 207: hp->nblocks = NBLKS - TO_BLKS(sizeof(SEGHDR)); ! 208: nfound = gbit_findfree(hp->segmap, nblks, NBLKS, &start); ! 209: if (nfound >= nblks) { ! 210: gbit_alloc(hp->segmap, start, nblks); ! 211: hp->nblocks -= nblks; ! 212: ! 213: /* convert block nr to pointer */ ! 214: chp = (LPSTR) hp; ! 215: chp = &chp[ (start-1) * BLKSIZE]; ! 216: /* add a handle into the block and skip past */ ! 217: * ( (HANDLE FAR *) chp) = hp->hseg; ! 218: chp += sizeof(HANDLE); ! 219: } ! 220: } ! 221: LeaveCriticalSection(&chainp->critsec); ! 222: memset(chp, 0, len); ! 223: return(chp); ! 224: } ! 225: ! 226: /*************************************************************************** ! 227: * Function: gmem_free ! 228: * ! 229: * Purpose: ! 230: * ! 231: * Free memory alloced ! 232: */ ! 233: void APIENTRY ! 234: gmem_free(HANDLE hHeap, LPSTR ptr, int len) ! 235: { ! 236: SEGHDRP chainp; ! 237: SEGHDRP hp; ! 238: HANDLE hmem; ! 239: long nblks, blknr; ! 240: LPSTR chp; ! 241: ! 242: if (len < 1) { ! 243: return; ! 244: } ! 245: ! 246: /* ! 247: * allocs greater than MAXGALLOC are too big to be worth ! 248: * allocing from the heap - they will have been allocated ! 249: * directly from globalalloc ! 250: */ ! 251: if (len > MAXGALLOC) { ! 252: hmem = GlobalHandle( (LPSTR) ptr); ! 253: GlobalUnlock(hmem); ! 254: GlobalFree(hmem); ! 255: return; ! 256: } ! 257: ! 258: chainp = (SEGHDRP) GlobalLock(hHeap); ! 259: EnterCriticalSection(&chainp->critsec); ! 260: ! 261: ! 262: /* just before the ptr we gave the user, is the handle to ! 263: * the block ! 264: */ ! 265: chp = (LPSTR) ptr; ! 266: chp -= sizeof(HANDLE); ! 267: hmem = * ((HANDLE FAR *) chp); ! 268: hp = (SEGHDRP) GlobalLock(hmem); ! 269: ! 270: nblks = TO_BLKS(len + sizeof(HANDLE)); ! 271: ! 272: /* convert ptr to block nr */ ! 273: blknr = TO_BLKS( (unsigned) (chp - (LPSTR) hp) ) + 1; ! 274: ! 275: gbit_free(hp->segmap, blknr, nblks); ! 276: hp->nblocks += nblks; ! 277: ! 278: GlobalUnlock(hmem); ! 279: ! 280: LeaveCriticalSection(&chainp->critsec); ! 281: GlobalUnlock(hHeap); ! 282: ! 283: } ! 284: ! 285: /*************************************************************************** ! 286: * Function: gmem_freeall ! 287: * ! 288: * Purpose: ! 289: * ! 290: * Free heap ! 291: */ ! 292: void APIENTRY ! 293: gmem_freeall(HANDLE hHeap) ! 294: { ! 295: SEGHDRP chainp; ! 296: HANDLE hSeg; ! 297: ! 298: chainp = (SEGHDRP) GlobalLock(hHeap); ! 299: /* this segment is always locked - so we need to unlock ! 300: * it here as well as below ! 301: */ ! 302: GlobalUnlock(hHeap); ! 303: ! 304: /* finished with the critical section - ! 305: * caller must ensure that at this point there is no ! 306: * longer any contention ! 307: */ ! 308: DeleteCriticalSection(&chainp->critsec); ! 309: ! 310: while (chainp != NULL) { ! 311: hSeg = chainp->hseg; ! 312: chainp = chainp->pnext; ! 313: GlobalUnlock(hSeg); ! 314: GlobalFree(hSeg); ! 315: } ! 316: } ! 317: ! 318: /*************************************************************************** ! 319: * Function: gmem_panic ! 320: * ! 321: * Purpose: ! 322: * ! 323: * A memory allocation attempt has failed. Return IDIGNORE to ignore the ! 324: * error and return NULL to the caller, and IDRETRY to retry the allocation ! 325: * attempt. ! 326: */ ! 327: int ! 328: gmem_panic(void) ! 329: { ! 330: int code; ! 331: ! 332: code = MessageBox(NULL, "Memory allocation failed", "Out Of Memory", ! 333: MB_ICONSTOP|MB_ABORTRETRYIGNORE); ! 334: if (code == IDABORT) { ! 335: /* abort this whole process */ ! 336: ExitProcess(1); ! 337: } else { ! 338: return(code); ! 339: } ! 340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.