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.

545 lines
13 KiB

  1. /*
  2. ** Copyright 1991, 1992, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. */
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #if DBG
  20. // Set glRandomMallocFail to a positive value, say 40, to enable random
  21. // allocation failures. The failure will occur every glRandomMallocFail
  22. // times.
  23. long glRandomMallocFail = 0;
  24. static long glRandomFailCount;
  25. // glSize is the size of memory in use.
  26. ULONG glSize = 0;
  27. ULONG glHighWater = 0;
  28. ULONG glReal = 0;
  29. static void AdjustSizes(LONG delta, void *mem)
  30. {
  31. ULONG nbytes;
  32. #ifdef GL_REAL_SIZE
  33. nbytes = HeapSize(GetProcessHeap(), 0, mem);
  34. #else
  35. nbytes = 0;
  36. #endif
  37. if (delta < 0)
  38. {
  39. glSize -= (ULONG)(-delta);
  40. glReal -= nbytes;
  41. if ((int) glSize < 0)
  42. {
  43. DBGPRINT("glSize underflows\n");
  44. }
  45. }
  46. else if (delta > 0)
  47. {
  48. glSize += delta;
  49. glReal += nbytes;
  50. if ((int) glSize < 0)
  51. {
  52. DBGPRINT("glSize overflows\n");
  53. }
  54. if (glSize > glHighWater)
  55. {
  56. #ifdef GL_SHOW_HIGH_WATER
  57. DbgPrint("glSize high %8d (%8d)\n", glSize, glReal);
  58. #endif
  59. glHighWater = glSize;
  60. }
  61. }
  62. }
  63. typedef struct _MEM_HDR
  64. {
  65. ULONG nbytes;
  66. ULONG signature[3];
  67. } MEM_HDR;
  68. // 'GLal' in byte order
  69. #define MEM_ALLOC_SIG 0x6C614C47
  70. // 'GLfr' in byte order
  71. #define MEM_FREE_SIG 0x72664C47
  72. #define MEM_HDR_SIZE sizeof(MEM_HDR)
  73. #define MEM_HDR_PTR(mem) ((MEM_HDR *)((BYTE *)(mem)-MEM_HDR_SIZE))
  74. // XXX We may want to protect these debug allocation functions with a
  75. // critical section.
  76. void * FASTCALL
  77. dbgAlloc(UINT nbytes, DWORD flags)
  78. {
  79. PVOID mem;
  80. // If random failure is enabled, fail this call randomly.
  81. if (glRandomMallocFail)
  82. {
  83. if (++glRandomFailCount >= glRandomMallocFail)
  84. {
  85. DBGPRINT("dbgAlloc random failing\n");
  86. glRandomFailCount = 0;
  87. return NULL;
  88. }
  89. }
  90. if (nbytes == 0)
  91. {
  92. DBGERROR("nbytes == 0\n");
  93. return NULL;
  94. }
  95. // Allocate extra bytes for debug house keeping.
  96. mem = HeapAlloc(GetProcessHeap(), flags, nbytes+MEM_HDR_SIZE);
  97. // Do house keeping and add allocation size so far.
  98. if (mem)
  99. {
  100. MEM_HDR *pmh = (MEM_HDR *)mem;
  101. pmh->nbytes = nbytes;
  102. pmh->signature[0] = MEM_ALLOC_SIG;
  103. pmh->signature[1] = MEM_ALLOC_SIG;
  104. pmh->signature[2] = MEM_ALLOC_SIG;
  105. AdjustSizes((LONG)nbytes, mem);
  106. mem = (PVOID) (pmh+1);
  107. }
  108. else
  109. {
  110. DBGLEVEL1(LEVEL_ERROR, "dbgAlloc could not allocate %u bytes\n",
  111. nbytes);
  112. }
  113. DBGLEVEL2(LEVEL_ALLOC, "dbgAlloc of %u returned 0x%x\n", nbytes, mem);
  114. return mem;
  115. }
  116. void FASTCALL
  117. dbgFree(void *mem)
  118. {
  119. MEM_HDR *pmh;
  120. if (!mem)
  121. {
  122. #ifdef FREE_OF_NULL_ERR
  123. // Freeing NULL happens currently so this error results
  124. // in a little too much spew.
  125. DBGERROR("mem is NULL\n");
  126. #endif
  127. return;
  128. }
  129. // Verify that the signature is not corrupted.
  130. pmh = MEM_HDR_PTR(mem);
  131. if (pmh->signature[0] != MEM_ALLOC_SIG ||
  132. pmh->signature[1] != MEM_ALLOC_SIG ||
  133. pmh->signature[2] != MEM_ALLOC_SIG)
  134. {
  135. WARNING("Possible memory corruption\n");
  136. }
  137. // Make sure it is freed once only.
  138. pmh->signature[0] = MEM_FREE_SIG;
  139. pmh->signature[1] = MEM_FREE_SIG;
  140. pmh->signature[2] = MEM_FREE_SIG;
  141. // Subtract the allocation size.
  142. AdjustSizes(-(LONG)pmh->nbytes, pmh);
  143. HeapFree(GetProcessHeap(), 0, pmh);
  144. DBGLEVEL1(LEVEL_ALLOC, "dbgFree of 0x%x\n", mem);
  145. }
  146. void * FASTCALL
  147. dbgRealloc(void *mem, UINT nbytes)
  148. {
  149. PVOID memNew;
  150. MEM_HDR *pmh;
  151. // If random failure is enabled, fail this call randomly.
  152. if (glRandomMallocFail)
  153. {
  154. if (++glRandomFailCount >= glRandomMallocFail)
  155. {
  156. DBGPRINT("dbgRealloc random failing\n");
  157. glRandomFailCount = 0;
  158. return NULL;
  159. }
  160. }
  161. if (mem != NULL)
  162. {
  163. // Verify that the signature is not corrupted.
  164. pmh = MEM_HDR_PTR(mem);
  165. if (pmh->signature[0] != MEM_ALLOC_SIG ||
  166. pmh->signature[1] != MEM_ALLOC_SIG ||
  167. pmh->signature[2] != MEM_ALLOC_SIG)
  168. {
  169. WARNING("Possible memory corruption\n");
  170. }
  171. AdjustSizes(-(LONG)pmh->nbytes, pmh);
  172. // Reallocate nbytes+extra bytes.
  173. memNew = HeapReAlloc(GetProcessHeap(), 0, pmh, nbytes+MEM_HDR_SIZE);
  174. }
  175. else
  176. {
  177. // Old memory pointer is NULL, so allocate a new chunk.
  178. memNew = HeapAlloc(GetProcessHeap(), 0, nbytes+MEM_HDR_SIZE);
  179. // We've allocated new memory so initialize its signature.
  180. if (memNew != NULL)
  181. {
  182. pmh = (MEM_HDR *)memNew;
  183. pmh->signature[0] = MEM_ALLOC_SIG;
  184. pmh->signature[1] = MEM_ALLOC_SIG;
  185. pmh->signature[2] = MEM_ALLOC_SIG;
  186. }
  187. }
  188. if (memNew != NULL)
  189. {
  190. // Do house keeping and update allocation size so far.
  191. AdjustSizes(nbytes, memNew);
  192. pmh = (MEM_HDR *)memNew;
  193. pmh->nbytes = nbytes;
  194. memNew = (PVOID) (pmh+1);
  195. }
  196. else
  197. {
  198. if (mem != NULL)
  199. {
  200. AdjustSizes((LONG)pmh->nbytes, pmh);
  201. }
  202. DBGLEVEL1(LEVEL_ERROR, "dbgRealloc could not allocate %u bytes\n",
  203. nbytes);
  204. }
  205. DBGLEVEL3(LEVEL_ALLOC, "dbgRealloc of 0x%X:%u returned 0x%x\n",
  206. mem, nbytes, memNew);
  207. return memNew;
  208. }
  209. int FASTCALL
  210. dbgMemSize(void *mem)
  211. {
  212. MEM_HDR *pmh;
  213. pmh = MEM_HDR_PTR(mem);
  214. if (pmh->signature[0] != MEM_ALLOC_SIG ||
  215. pmh->signature[1] != MEM_ALLOC_SIG ||
  216. pmh->signature[2] != MEM_ALLOC_SIG)
  217. {
  218. return -1;
  219. }
  220. return (int)pmh->nbytes;
  221. }
  222. #endif // DBG
  223. ULONG APIENTRY glDebugEntry(int param, void *data)
  224. {
  225. #if DBG
  226. switch(param)
  227. {
  228. case 0:
  229. return glSize;
  230. case 1:
  231. return glHighWater;
  232. case 2:
  233. return glReal;
  234. case 3:
  235. return dbgMemSize(data);
  236. }
  237. #endif
  238. return 0;
  239. }
  240. #define MEM_ALIGN 32
  241. void * FASTCALL
  242. AllocAlign32(UINT nbytes)
  243. {
  244. void *mem;
  245. void **aligned;
  246. // We allocate enough extra memory for the alignment and our header
  247. // which just consists of a pointer:
  248. mem = ALLOC(nbytes + MEM_ALIGN + sizeof(void *));
  249. if (!mem)
  250. {
  251. DBGLEVEL1(LEVEL_ERROR, "AllocAlign32 could not allocate %u bytes\n",
  252. nbytes);
  253. return NULL;
  254. }
  255. aligned = (void **)(((ULONG_PTR)mem + sizeof(void *) +
  256. (MEM_ALIGN - 1)) & ~(MEM_ALIGN - 1));
  257. *(aligned-1) = mem;
  258. return aligned;
  259. }
  260. void FASTCALL
  261. FreeAlign32(void *mem)
  262. {
  263. if ( NULL == mem )
  264. {
  265. DBGERROR("NULL pointer passed to FreeAlign32\n");
  266. return;
  267. }
  268. FREE(*((void **)mem-1));
  269. }
  270. void * FASTCALL
  271. gcAlloc( __GLcontext *gc, UINT nbytes, DWORD flags )
  272. {
  273. void *mem;
  274. #if DBG
  275. mem = dbgAlloc(nbytes, flags);
  276. #else
  277. mem = HeapAlloc(GetProcessHeap(), flags, nbytes);
  278. #endif
  279. if (NULL == mem)
  280. {
  281. ((__GLGENcontext *)gc)->errorcode = GLGEN_OUT_OF_MEMORY;
  282. __glSetErrorEarly(gc, GL_OUT_OF_MEMORY);
  283. }
  284. return mem;
  285. }
  286. void * FASTCALL
  287. GCREALLOC( __GLcontext *gc, void *mem, UINT nbytes )
  288. {
  289. void *newMem;
  290. // The Win32 realloc functions do not have free-on-zero behavior,
  291. // so fake it.
  292. if (nbytes == 0)
  293. {
  294. if (mem != NULL)
  295. {
  296. FREE(mem);
  297. }
  298. return NULL;
  299. }
  300. // The Win32 realloc functions don't handle a NULL old pointer,
  301. // so explicitly turn such calls into allocs.
  302. if (mem == NULL)
  303. {
  304. newMem = ALLOC(nbytes);
  305. }
  306. else
  307. {
  308. newMem = REALLOC(mem, nbytes);
  309. }
  310. if (NULL == newMem)
  311. {
  312. ((__GLGENcontext *)gc)->errorcode = GLGEN_OUT_OF_MEMORY;
  313. __glSetErrorEarly(gc, GL_OUT_OF_MEMORY);
  314. }
  315. return newMem;
  316. }
  317. void * FASTCALL
  318. GCALLOCALIGN32( __GLcontext *gc, UINT nbytes )
  319. {
  320. void *mem;
  321. mem = AllocAlign32(nbytes);
  322. if (NULL == mem)
  323. {
  324. ((__GLGENcontext *)gc)->errorcode = GLGEN_OUT_OF_MEMORY;
  325. __glSetErrorEarly(gc, GL_OUT_OF_MEMORY);
  326. }
  327. return mem;
  328. }
  329. // Tunable parameters for temporary memory allocation
  330. #define MAX_TEMP_BUFFERS 4
  331. #define TEMP_BUFFER_SIZE 4096
  332. struct MemHeaderRec
  333. {
  334. LONG inUse;
  335. ULONG nbytes;
  336. void *mem;
  337. };
  338. typedef struct MemHeaderRec MemHeader;
  339. MemHeader TempMemHeader[MAX_TEMP_BUFFERS];
  340. // InitTempAlloc
  341. // Initializes the temporary memory allocation header and allocates the
  342. // temporary memory buffers.
  343. //
  344. // Synopsis:
  345. // BOOL InitTempAlloc()
  346. //
  347. // History:
  348. // 02-DEC-93 Eddie Robinson [v-eddier] Wrote it.
  349. //
  350. BOOL FASTCALL
  351. InitTempAlloc(void)
  352. {
  353. int i;
  354. PBYTE buffers;
  355. static LONG initCount = -1;
  356. if (initCount >= 0)
  357. return TRUE;
  358. if (InterlockedIncrement(&initCount) != 0)
  359. return TRUE;
  360. // Allocate buffers for the first time.
  361. buffers = ALLOC(MAX_TEMP_BUFFERS*TEMP_BUFFER_SIZE);
  362. if (!buffers)
  363. {
  364. InterlockedDecrement(&initCount); // try again later
  365. return FALSE;
  366. }
  367. for (i = 0; i < MAX_TEMP_BUFFERS; i++)
  368. {
  369. TempMemHeader[i].nbytes = TEMP_BUFFER_SIZE;
  370. TempMemHeader[i].mem = (void *) buffers;
  371. TempMemHeader[i].inUse = -1; // must be last
  372. buffers += TEMP_BUFFER_SIZE;
  373. }
  374. return TRUE;
  375. }
  376. // gcTempAlloc
  377. // Allocates temporary memory from a static array, if possible. Otherwise
  378. // it calls ALLOC
  379. //
  380. // Synopsis:
  381. // void * gcTempAlloc(__GLcontext *gc, UINT nbytes)
  382. // gc points to the OpenGL context structure
  383. // nbytes specifies the number of bytes to allocate
  384. //
  385. // History:
  386. // 02-DEC-93 Eddie Robinson [v-eddier] Wrote it.
  387. //
  388. void * FASTCALL
  389. gcTempAlloc(__GLcontext *gc, UINT nbytes)
  390. {
  391. int i;
  392. void *mem;
  393. if (nbytes == 0)
  394. {
  395. // Zero-byte allocations do occur so don't make this a warning
  396. // to avoid excessive debug spew.
  397. DBGLEVEL(LEVEL_ALLOC, "gcTempAlloc: failing zero byte alloc\n");
  398. return NULL;
  399. }
  400. for (i = 0; i < MAX_TEMP_BUFFERS; i++)
  401. {
  402. if (nbytes <= TempMemHeader[i].nbytes)
  403. {
  404. if (InterlockedIncrement(&TempMemHeader[i].inUse))
  405. {
  406. InterlockedDecrement(&TempMemHeader[i].inUse);
  407. }
  408. else
  409. {
  410. DBGLEVEL2(LEVEL_ALLOC, "gcTempAlloc of %u returned 0x%x\n",
  411. nbytes, TempMemHeader[i].mem);
  412. GC_TEMP_BUFFER_ALLOC(gc, TempMemHeader[i].mem);
  413. return(TempMemHeader[i].mem);
  414. }
  415. }
  416. }
  417. mem = ALLOC(nbytes);
  418. if (!mem)
  419. {
  420. WARNING1("gcTempAlloc: memory allocation error size %d\n", nbytes);
  421. ((__GLGENcontext *)gc)->errorcode = GLGEN_OUT_OF_MEMORY;
  422. __glSetErrorEarly(gc, GL_OUT_OF_MEMORY);
  423. }
  424. DBGLEVEL2(LEVEL_ALLOC, "gcTempAlloc of %u returned 0x%x\n", nbytes, mem);
  425. GC_TEMP_BUFFER_ALLOC(gc, mem);
  426. return mem;
  427. }
  428. // gcTempFree
  429. // Marks allocated static buffer as unused or calls FREE.
  430. //
  431. // Synopsis:
  432. // void gcTempFree(__GLcontext *gc, void *mem)
  433. // mem specifies the adress of the memory to free
  434. //
  435. // History:
  436. // 02-DEC-93 Eddie Robinson [v-eddier] Wrote it.
  437. //
  438. void FASTCALL
  439. gcTempFree(__GLcontext *gc, void *mem)
  440. {
  441. int i;
  442. DBGLEVEL1(LEVEL_ALLOC, "gcTempFree of 0x%x\n", mem);
  443. GC_TEMP_BUFFER_FREE(gc, mem);
  444. for (i = 0; i < MAX_TEMP_BUFFERS; i++)
  445. {
  446. if (mem == TempMemHeader[i].mem)
  447. {
  448. InterlockedDecrement(&TempMemHeader[i].inUse);
  449. return;
  450. }
  451. }
  452. FREE( mem );
  453. }