Annotation of mstools/samples/sdktools/windiff/gmem.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.