Leaked source code of windows server 2003
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.

447 lines
13 KiB

  1. /*
  2. * @DEC_COPYRIGHT@
  3. */
  4. /*
  5. * HISTORY
  6. * $Log: sc_mem.c,v $
  7. * Revision 1.1.4.2 1996/01/02 18:30:56 Bjorn_Engberg
  8. * Got rid of compiler warnings: Added include files for NT.
  9. * [1996/01/02 15:25:04 Bjorn_Engberg]
  10. *
  11. * Revision 1.1.2.4 1995/09/20 14:59:33 Bjorn_Engberg
  12. * Port to NT
  13. * [1995/09/20 14:41:14 Bjorn_Engberg]
  14. *
  15. * Revision 1.1.2.3 1995/09/14 17:28:09 Bjorn_Engberg
  16. * Ported to NT
  17. * [1995/09/14 17:21:10 Bjorn_Engberg]
  18. *
  19. * Revision 1.1.2.2 1995/05/31 18:07:53 Hans_Graves
  20. * Inclusion in new SLIB location.
  21. * [1995/05/31 16:15:46 Hans_Graves]
  22. *
  23. * Revision 1.1.2.2 1995/05/03 19:12:55 Hans_Graves
  24. * First time under SLIB
  25. * [1995/05/03 19:12:17 Hans_Graves]
  26. *
  27. * Revision 1.1.2.3 1995/04/17 17:46:54 Hans_Graves
  28. * Added ScAlloc2()
  29. * [1995/04/17 17:45:28 Hans_Graves]
  30. *
  31. * Revision 1.1.2.2 1995/04/07 18:40:03 Hans_Graves
  32. * Inclusion in SLIB's Su library
  33. * [1995/04/07 18:39:43 Hans_Graves]
  34. *
  35. * $EndLog$
  36. */
  37. /*****************************************************************************
  38. ** Copyright (c) Digital Equipment Corporation, 1993 **
  39. ** **
  40. ** All Rights Reserved. Unpublished rights reserved under the copyright **
  41. ** laws of the United States. **
  42. ** **
  43. ** The software contained on this media is proprietary to and embodies **
  44. ** the confidential technology of Digital Equipment Corporation. **
  45. ** Possession, use, duplication or dissemination of the software and **
  46. ** media is authorized only pursuant to a valid written license from **
  47. ** Digital Equipment Corporation. **
  48. ** **
  49. ** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
  50. ** Government is subject to restrictions as set forth in Subparagraph **
  51. ** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
  52. ******************************************************************************/
  53. /*-------------------------------------------------------------------------
  54. ** Modification History: sc_mem.c
  55. ** 05-29-93 Victor Bahl Paged aligned malloc and free
  56. ** 12-07-93 PSG Added error reporting code
  57. ** 03-15-95 HWG Moved to Su library, Added SuAlloc & SuFree
  58. ** 04-04-97 HWG With WIN32 use LocalAlloc and LocalFree in
  59. ** place of malloc and free
  60. ** Added ScCalloc function.
  61. ** 04-15-97 HWG Added memory linked list to help track leaks
  62. ** Fixed potential initalization bug in linked
  63. ** list used to track ScPaMalloc's
  64. --------------------------------------------------------------------------*/
  65. /*
  66. #define _SLIBDEBUG_
  67. */
  68. #include <stdio.h> /* NULL */
  69. #include <sys/types.h>
  70. #ifdef WIN32
  71. #include <windows.h>
  72. #include <stdlib.h>
  73. #include <malloc.h>
  74. #endif /* WIN32 */
  75. #include "SC.h"
  76. #include "SC_err.h"
  77. #ifdef _SLIBDEBUG_
  78. #include "sc_debug.h"
  79. #define _DEBUG_ 0 /* detailed debuging statements */
  80. #define _VERBOSE_ 0 /* show progress */
  81. #define _VERIFY_ 1 /* verify correct operation */
  82. #define _WARN_ 1 /* warnings about strange behavior */
  83. /* keep a linked list to ttrack memory leaks */
  84. typedef struct memblock_s {
  85. void *ptr;
  86. dword size;
  87. dword counter;
  88. char desc[15];
  89. struct memblock_s *next;
  90. } memblock_t;
  91. static memblock_t *_blocklist=NULL;
  92. static _blockcounter=0;
  93. static _memused=0;
  94. void scMemAddWatch(void *ptr, dword size, char *desc)
  95. {
  96. memblock_t *pblock;
  97. #if defined(WIN32)
  98. pblock = (void *)LocalAlloc(LPTR, sizeof(memblock_t));
  99. #else
  100. pblock = (void *)malloc(sizeof(memblock_t));
  101. #endif
  102. _memused+=size;
  103. if (pblock)
  104. {
  105. pblock->ptr=ptr;
  106. pblock->next=_blocklist;
  107. pblock->size=size;
  108. pblock->counter=_blockcounter;
  109. if (desc==NULL)
  110. pblock->desc[0]=0;
  111. else
  112. {
  113. int i;
  114. for (i=0; desc[i] && i<14; i++)
  115. pblock->desc[i]=desc[i];
  116. pblock->desc[i]=0;
  117. }
  118. _blocklist=pblock;
  119. _blockcounter++;
  120. }
  121. }
  122. ScBoolean_t scMemRemoveWatch(void *ptr)
  123. {
  124. memblock_t *plastblock=NULL, *pblock=_blocklist;
  125. while (pblock)
  126. {
  127. if (pblock->ptr==ptr) /* remove from list */
  128. {
  129. if (plastblock==NULL) /* beginning of linked list */
  130. _blocklist=pblock->next;
  131. else
  132. plastblock->next=pblock->next;
  133. _memused-=pblock->size;
  134. #ifdef WIN32
  135. LocalFree(pblock);
  136. #else
  137. free(pblock);
  138. #endif
  139. if (_blocklist==NULL) /* all memory freed, reset counter */
  140. _blockcounter=0;
  141. return(TRUE);
  142. }
  143. plastblock=pblock;
  144. pblock=pblock->next;
  145. }
  146. return(FALSE);
  147. }
  148. dword scMemDump()
  149. {
  150. memblock_t *plastblock=NULL, *pblock=_blocklist;
  151. ScDebugPrintf(NULL, "scMemDump: memused=%ld\n", _memused);
  152. while (pblock)
  153. {
  154. ScDebugPrintf(NULL, " ptr=%p counter=%ld size=%ld desc=%s\n",
  155. pblock->ptr, pblock->counter, pblock->size, pblock->desc);
  156. pblock=pblock->next;
  157. }
  158. return(_memused);
  159. }
  160. #endif
  161. #ifdef WIN32
  162. int getpagesize()
  163. {
  164. SYSTEM_INFO sysInfo;
  165. static int pagesize = 0 ;
  166. if( pagesize == 0 ) {
  167. GetSystemInfo(&sysInfo);
  168. pagesize = (int)sysInfo.dwPageSize;
  169. }
  170. return pagesize ;
  171. }
  172. #define bzero(_addr_,_len_) memset(_addr_,0,_len_)
  173. #endif
  174. /*------------------------------------------------------------------------
  175. Simple Memory Allocation
  176. -------------------------------------------------------------------------*/
  177. /*
  178. ** Name: ScAlloc
  179. ** Purpose: Allocate number of bytes of memory.
  180. **
  181. */
  182. void *ScAlloc(unsigned long bytes)
  183. {
  184. void *ptr;
  185. #ifdef MACINTOSH
  186. ptr = NewPtr(bytes);
  187. #elif MSC60
  188. ptr = (void FAR *) _fmalloc((unsigned int)bytes); /* far memory */
  189. #elif defined(WIN32)
  190. ptr = (void *)LocalAlloc(LPTR, bytes);
  191. #else
  192. ptr = (void *)malloc(bytes);
  193. #endif
  194. _SlibDebug(ptr, scMemAddWatch(ptr, bytes, NULL) );
  195. _SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScAlloc(%ld) returns %p\n",bytes,ptr) );
  196. return(ptr);
  197. }
  198. /*
  199. ** Name: ScCalloc
  200. ** Purpose: Allocate number of bytes of memory and zero it out.
  201. **
  202. */
  203. void *ScCalloc(unsigned long bytes)
  204. {
  205. void *ptr = ScAlloc(bytes);
  206. if (ptr != NULL)
  207. {
  208. #ifdef MSC60
  209. _fmemset(ptr, 0, (unsigned int)bytes);
  210. #else
  211. memset(ptr, 0, bytes);
  212. #endif
  213. }
  214. _SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScCalloc(%ld) returns %p\n",bytes,ptr) );
  215. return(ptr);
  216. }
  217. /*
  218. ** Name: ScAlloc2
  219. ** Purpose: Allocate number of bytes of memory equal to "bytes".
  220. ** Takes an extra argument "name" which identifies the block
  221. ** (used for debugging).
  222. */
  223. void *ScAlloc2(unsigned long bytes, char *desc)
  224. {
  225. void *ptr;
  226. ptr = ScAlloc(bytes);
  227. #ifdef _SLIBDEBUG_
  228. if (_blocklist) /* copy description to leak tracking info */
  229. {
  230. int i;
  231. for (i=0; desc[i] && i<14; i++)
  232. _blocklist->desc[i]=desc[i];
  233. _blocklist->desc[i]=0;
  234. }
  235. #endif
  236. _SlibDebug(_DEBUG_,
  237. ScDebugPrintf(NULL, "ScAlloc(%ld, %s) returns %p\n",bytes,desc,ptr) );
  238. return(ptr);
  239. }
  240. /*
  241. ** Name: ScFree
  242. ** Purpose: Free memory pointed to by "*ptr_addr"
  243. **
  244. */
  245. void ScFree(void *ptr)
  246. {
  247. _SlibDebug(_DEBUG_, ScDebugPrintf(NULL, "ScFree(%p)\n", ptr) );
  248. _SlibDebug(ptr, scMemRemoveWatch(ptr) );
  249. if (ptr != NULL)
  250. {
  251. #ifdef MACINTOSH
  252. DisposPtr(ptr);
  253. #elif defined(WIN32)
  254. #ifdef _SLIBDEBUG_
  255. _SlibDebug(LocalFree(ptr)!=NULL, ScDebugPrintf(NULL, "ScFree(%p) failed\n", ptr) );
  256. #else
  257. LocalFree(ptr);
  258. #endif
  259. #else
  260. free(ptr);
  261. #endif
  262. }
  263. }
  264. /*
  265. ** Name: ScMemCheck
  266. ** Purpose: Check block of memory all equal to a single byte,
  267. ** else return FALSE
  268. */
  269. int ScMemCheck(char *array, int test, int num)
  270. {
  271. int i=0;
  272. /* 'test' is only tested as a char (bottom 8 bits) */
  273. while (array[i] == test && i<num)
  274. i++;
  275. if (i==num)
  276. return TRUE;
  277. else
  278. return FALSE;
  279. }
  280. /*------------------------------------------------------------------------
  281. Paged aligned malloc() and free()
  282. -------------------------------------------------------------------------*/
  283. /*
  284. ** This structure is used by the page align malloc/free support code.
  285. ** These "working sets" will contain the malloc-ed address and the
  286. ** page aligned address for the free*() call.
  287. */
  288. typedef struct mpa_ws_s
  289. {
  290. char *palign_addr; /* the page aligned address that's used */
  291. char *malloc_addr; /* the malloc-ed address to free */
  292. struct mpa_ws_s *next; /* for the next on the list */
  293. } mpa_ws_t;
  294. /*
  295. ** Initialized and uninitialized data.
  296. */
  297. static mpa_ws_t *mpa_qhead=NULL; /* local Q head for the malloc stuctures */
  298. /*
  299. ** Name: ScPaMalloc
  300. ** Purpose: Allocate Paged Alligned Memory
  301. ** This routine allocates and returns to the caller a system
  302. ** page aligned buffer. Enough space will be added, one more
  303. ** page, to allow the pointers to be adjusted to the next page
  304. ** boundry. A local linked list will keep copies of the original
  305. ** and adjusted addresses. This list will be used by sv_PaFree()
  306. ** to free the correct buffer.
  307. **
  308. */
  309. char *ScPaMalloc(int size)
  310. {
  311. mpa_ws_t *ws; /* pointer for the working set */
  312. ULONG_PTR tptr; /* to store pointer temp for bit masking */
  313. int PageSize = getpagesize(); /* system's page size */
  314. /*
  315. ** The space for the working set structure that will go on the queue
  316. ** is allocated first.
  317. */
  318. if ((ws = (mpa_ws_t *)ScAlloc(sizeof(mpa_ws_t))) == (mpa_ws_t *)NULL)
  319. return( (char *)NULL );
  320. /*
  321. ** Using the requested size, from the argument list, and the page size
  322. ** from the system, allocate enough space to page align the requested
  323. ** buffer. The original request will have the space of one system page
  324. ** added to it. The pointer will be adjusted.
  325. */
  326. ws->malloc_addr = (char *)ScAlloc(size + PageSize);
  327. if (ws->malloc_addr == (char *)NULL)
  328. {
  329. ScFree(ws); /* not going to be used */
  330. return((char *)NULL); /* signal the failure */
  331. } else
  332. (void) bzero (ws->malloc_addr, (size + PageSize));
  333. /*
  334. ** Now using the allocated space + 1 page, adjust the pointer to
  335. ** point to the next page boundry.
  336. */
  337. ws->palign_addr = ws->malloc_addr + PageSize; /* to the next page */
  338. /*
  339. ** Using the page size and subtracting 1 to get a bit mask, mask off
  340. ** the low order "page offset" bits to get the aligned address. Now the
  341. ** aligned pointer will contain the address of the next page with enough
  342. ** space to hold the users requested size.
  343. */
  344. tptr = (ULONG_PTR)ws->palign_addr; /* copy to local int */
  345. tptr &= (ULONG_PTR)(~(PageSize - 1)); /* Mask addr bit to the */
  346. ws->palign_addr = (char *)tptr; /* put back the address */
  347. /*
  348. ** Put the working set onto the linked list so that the original
  349. ** malloc-ed buffer can be freeed when the user program is done with it.
  350. */
  351. ws->next=mpa_qhead;
  352. mpa_qhead=ws; /* just put it at the head */
  353. /*
  354. ** Now return the aligned address to the caller.
  355. */
  356. return((char *)ws->palign_addr);
  357. }
  358. /*
  359. ** Name: ScPaFree
  360. ** Purpose: This is a local free routine to return to the system a previously
  361. ** alloc-ed buffer. A local linked list keeps copies of the original
  362. ** and adjusted addresses. This list is used by this routine to free
  363. ** the correct buffer.
  364. */
  365. void ScPaFree (void *pa_addr)
  366. {
  367. mpa_ws_t *p, *q; /* walkers for the malloc list */
  368. /*
  369. ** Walk along the malloc-ed memory linked list, watch for a match
  370. ** on the page aligned address. If a match is found break out of the
  371. ** loop.
  372. */
  373. p = mpa_qhead; /* set the pointers */
  374. q = NULL;
  375. while (p != NULL)
  376. {
  377. if (p->palign_addr == pa_addr) /* found the buffer */
  378. break;
  379. q = p; /* save current */
  380. p = p->next; /* get next */
  381. }
  382. _SlibDebug(_WARN_ && p==NULL,
  383. ScDebugPrintf(NULL, "ScPaFree(%p) Illegal pointer\n", pa_addr) );
  384. /*
  385. ** After falling out of the loop the pointers are at the place where
  386. ** some work has to be done, (this could also be at the beginning).
  387. ** If a match is found call the free() routine to return the buffer, if
  388. ** the loop fell off the end just return.
  389. */
  390. if (p != NULL)
  391. {
  392. /*
  393. ** Where on the list is it, check for making it empty.
  394. */
  395. if (q == NULL) /* at the front */
  396. mpa_qhead = p->next; /* pop off front */
  397. else /* inside the list */
  398. q->next = p->next; /* pop it */
  399. ScFree(p->malloc_addr); /* free the malloc-ed addr */
  400. /*
  401. ** Now free up the working set, it is not needed any more.
  402. */
  403. ScFree(p);
  404. }
  405. }