Source code of Windows XP (NT5)
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.

1210 lines
37 KiB

  1. /*
  2. * This software and its associated documentation are protected by
  3. * Copyright 1995 Geodesic Systems Inc. All Rights Reserved.
  4. * Portions of the software include modification to code which was
  5. * released publicly by Xerox Corporation, subject to the requirement that
  6. * the following notice be retained and included with the modified code:
  7. * "Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers.
  8. * Copyright (c) 1991-1995 by Xerox Corporation.
  9. * All rights reserved. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY
  10. * NO WARRANTY EXPRESS OR IMPLIED. ANY USE IS AT YOUR OWN RISK."
  11. */
  12. /* Fiterman, May 8, 1997 14:20 am CST */
  13. #ifndef _GCT_H
  14. # define _GCT_H
  15. # ifdef __cplusplus
  16. extern "C" {
  17. # endif
  18. # include <stddef.h>
  19. # include <stdlib.h>
  20. #define NO_PARAMS void
  21. #ifdef __cplusplus
  22. # undef NO_PARAMS
  23. #endif
  24. #ifndef NO_PARAMS
  25. # define NO_PARAMS
  26. #endif
  27. #ifdef GC_BUILD_DLL
  28. # define GC_SYS_IMPORT __declspec(dllimport)
  29. # define GC_IMPORTX __declspec(dllexport)
  30. # define GC_EXPORT __declspec(dllexport)
  31. # ifdef GC_CRTDLL
  32. # define GC_EXPORTY(t) __declspec(dllexport) t
  33. # else
  34. # define GC_EXPORTY(t) t
  35. # endif
  36. # define GC_EXPORTX(t) GC_EXPORTY(t) __cdecl
  37. #else /* GC_BUILD_DLL */
  38. # define GC_IMPORTX __declspec(dllimport)
  39. # define GC_EXPORTX(t) __declspec(dllimport) t
  40. # ifdef __cplusplus
  41. # define gcInitFunction extern "C" __declspec(dllexport) void __cdecl
  42. # else
  43. # define gcInitFunction __declspec(dllexport) void
  44. # endif
  45. # define GC_EXPORTY(x) x
  46. #endif /* GC_BUILD_DLL */
  47. #define GC_IMPORT extern GC_IMPORTX
  48. /*
  49. * Define word and signed_word to be unsigned and signed types of the
  50. * size as char * or void *. There seems to be no way to do this
  51. * even semi-portably. The following is probably no better/worse
  52. * than almost anything else
  53. * The ANSI standard suggests that size_t and ptr_diff_t might be
  54. * better choices. But those appear to have incorrect definitions
  55. * on may systems. Notably "typedef int size_t" seems to be both
  56. * frequent and WRONG
  57. */
  58. typedef unsigned long gcWord;
  59. typedef long gcSignedWord;
  60. /* Public read-only variables */
  61. GC_IMPORT gcWord gcCollections; /* Counter incremented per collection. */
  62. /* Public R/W variables */
  63. /*
  64. * Non zero Enables logging output. This involves a performance
  65. * cost and is thus not the default.
  66. */
  67. GC_IMPORT long gcPrintStats;
  68. /*
  69. * Print memory usage statistics
  70. */
  71. GC_IMPORT int gcPrintMemUsage;
  72. /*
  73. * Consider as roots all non heap mappings where pointers can be found
  74. * Sunos only
  75. */
  76. GC_IMPORT int gcScanAllPotentialRoots;
  77. /* Disable signals in critical sections of the collector */
  78. GC_IMPORT int gcDisableSignalsSwitch;
  79. /* Memory explicitly freed before next footprint-reduce */
  80. GC_IMPORT unsigned long gcMaxMemFreedBeforeNextFootPrintReduce;
  81. /*
  82. * Some applications like netscape with java change the location of
  83. * the execution stack (Argh!). This causes the collector to smash memory when
  84. * cleaning the stack. When this variable is set to 0, the stack is cleaned
  85. * just a little above the current sp. This prevents netscape with java from
  86. * crashing.
  87. */
  88. GC_IMPORT int gcAllowUserStacks;
  89. /*
  90. * Memory usage statistics are obtained at the end of a garbage collection
  91. * This variable forces a collection every so many bytes allocated.
  92. * The initialy value is 1 Mb and it can be changed at run time with
  93. * an environment var.
  94. */
  95. GC_IMPORT unsigned long gcBytesBeforeNextStatistics;
  96. /*
  97. * Non zero enables collect at end. Defaults to 1 for report
  98. * libs and zero otherwise.
  99. */
  100. GC_IMPORT int gcCollectAtEnd;
  101. /*
  102. * Defaults to zero which implies not flushing the log file.
  103. * If gcFlushLog > 0 flush the log file every gcFlushLog lines.
  104. */
  105. GC_IMPORT int gcFlushLog;
  106. /*
  107. * Normally non leaf objects are zeroed to avoid spotting pointers
  108. * in them when they are reallocated. Setting this to zero prevents
  109. * that and may speed up some programs.
  110. */
  111. GC_IMPORT int gcZeroAllocatedObject;
  112. /*
  113. * Non zero enables free(). zero causes free() to be ignored.
  114. * defaults to one. Not used in the report libraries.
  115. */
  116. GC_IMPORT char gcEnableFree;
  117. /*
  118. * gcFixPrematureFrees() sets gcEnableFree to 0; and other
  119. * tuning stuff. Fixing premature frees may increase memory
  120. * usage. gcStopFixingPrematureFrees(NO_PARAMS) has the opposite
  121. * effect. Both functions return nonzero if premature frees
  122. * were previously being fixed.
  123. */
  124. GC_EXPORTX(int) gcFixPrematureFrees(NO_PARAMS);
  125. GC_EXPORTX(int) gcStopFixingPrematureFrees(NO_PARAMS);
  126. /*
  127. * If gcEnableFree is zero and gcFreeProcessOldObject is non
  128. * zero it will be called to process the free()ed object.
  129. * gcFreeProcessOldObject defaults to zero. gcDefaultFreeProcessOldObject
  130. * will zero old objects which seems a reasonable.
  131. */
  132. typedef void (* gcObjectFunction)(void *obj, size_t size);
  133. GC_EXPORTX(void) gcDefaultFreeProcessOldObject(void *obj, size_t size);
  134. GC_IMPORT gcObjectFunction gcFreeProcessOldObject;
  135. /*
  136. * This points to the name of the log file. It is initially aimed at
  137. * "gc.log", it is used to create the log file the first time output
  138. * is done, after that it is never used. This constant is contained
  139. * in a separate module so it can be replaced before startup.
  140. */
  141. typedef const char * gcConstCharStar;
  142. GC_IMPORT gcConstCharStar gcLogFile;
  143. /*
  144. * Activates stack tracing on the position where items are allocated.
  145. * Only used when linked to a debug library.
  146. */
  147. GC_IMPORT int gcShowStackTrace;
  148. /*
  149. * When an attempted allocation fails, Great Circle must decide whether to
  150. * collect or expand the heap. gcNotTransparent != 0 says always expand
  151. * this until stopped by gcSetMaxHeapSize or a failure to expand.
  152. * gcDontExpand != 0 says always collect but then expand if that isn't enough.
  153. *
  154. * Otherwise collect if (M > N/(gcPriority + 1)) where N is the heap size plus
  155. * a rough estimate of the root set size, and M is the amount allocated since
  156. * the last complete collection.
  157. *
  158. * Initially, gcPriority = 3, increasing its value will use less space but
  159. * more collection time. Decreasing it will appreciably decrease collection
  160. * time at the expense of space. gcPriority = 0 will cause the equation to
  161. * always choose expand. Setting incremental mode or pseudo incremental mode
  162. * effectivly doubles gcPriority. Since a single paging operation is likely
  163. * to eat more time than the collector ever could, increasing the number of
  164. * collections has the paradoxical effect of speeding up some programs.
  165. *
  166. * If you call gcAttemptCollection() the equation (M > N/(gcPriority + 1))
  167. * will determine if a collection actually takes place.
  168. */
  169. GC_IMPORT unsigned gcPriority;
  170. GC_IMPORT int gcNotTransparent;
  171. GC_IMPORT int gcDontExpand;
  172. /*
  173. * Number of partial collections between full collections.
  174. * Matters only if gcIncremental is set.
  175. */
  176. GC_IMPORT int gcFullFrequency;
  177. #ifdef GC_DEBUG
  178. #define GC_DEBUG_BOUNDS_CHECK 1
  179. #define GC_DEBUG_LINE_NUMBERS 1
  180. #define GC_WRAPPED_NEW new(__FILE__, __LINE__)
  181. #else
  182. #define GC_WRAPPED_NEW new
  183. #endif
  184. /* Public procedures */
  185. /*
  186. * General purpose allocation routines, with malloc calling conventions.
  187. * The leaf versions promise that no relevant pointers are contained
  188. * in the object. The nonleaf versions guarantee that the new object
  189. * is cleared. gcMallocManual allocates an object that is scanned
  190. * for pointers to collectible objects, but is not itself collectible.
  191. */
  192. GC_EXPORTX(void *) gcMalloc(size_t size_in_bytes);
  193. GC_EXPORTX(void *) gcMallocLeaf(size_t size_in_bytes);
  194. GC_EXPORTX(void *) gcMallocManual(size_t size_in_bytes);
  195. /*
  196. * Explicitly deallocate an object. Dangerous if used incorrectly.
  197. * Requires a pointer to the base of an object.
  198. * An object should not be enabled for finalization when it is
  199. * explicitly deallocated.
  200. * gcFree(0) is a no-op, as required by ANSI C for free.
  201. */
  202. GC_EXPORTX(void) gcFree(void * object_addr);
  203. /*
  204. * gcMallocIgnoreOffPage reduces the chance of accidentally retaining
  205. * a large, > 4096 byte, object as a result of scanning an integer
  206. * that happens to be an address inside the array. Large arrays usually
  207. * are only used where there is a pointer to the beginning of the array.
  208. *
  209. * This was built around the needs of very large Xwindows programs, we
  210. * have discovered that it works well with almost all programs, improving
  211. * space and speed efficiency.
  212. *
  213. * gcMallocIgnoreOffPage(lb) acts like malloc(lb) except that only pointers
  214. * to the first 4096 bytes will be used by the collector to keep the
  215. * object alive. If lb is smaller than 4K it acts exactly like malloc.
  216. *
  217. * gcMallocIgnoreOffPage is the connection for malloc(lb) where
  218. * lb > gcVeryLargeAllocationSize && gcIgnoreOffPage
  219. *
  220. * gcVeryLargeAllocationSize is initialized to 100000.
  221. *
  222. * gcIgnoreOffPage is in a separate module in the libraries to
  223. * allow you to replace it in programs where you have no source code, or
  224. * where you need it replaced before startup code runs. This also effects
  225. * calloc and realloc. It is initialized to 1 except in the gcsome and
  226. * gcsomedb libraries where it is initialized to 0.
  227. *
  228. * If we need a block N bytes long and have a block > N + gcBlackSizeLimit
  229. * and N > gcBlackSizeLimit but all possible positions in it are
  230. * the targets of apparent pointers, we use it anyway and print a warning.
  231. * This risks leaking the block due to a false reference. But not using
  232. * it risks unreasonable immeadiate heap growth. gcBlackSizeLimit defaults
  233. * to 100K.
  234. */
  235. GC_EXPORTX(void *) gcMallocIgnoreOffPage(size_t lb);
  236. GC_EXPORTX(void *) gcMallocLeafIgnoreOffPage(size_t lb);
  237. GC_IMPORT unsigned long gcVeryLargeAllocationSize;
  238. GC_IMPORT int gcIgnoreOffPage;
  239. GC_IMPORT long gcBlackSizeLimit;
  240. /* Kinds of objects */
  241. # define gcLeafObject 0
  242. # define gcCollectibleObject 1
  243. # define gcManualObject 2
  244. /*
  245. * Return the kind of an object, gcLeafObject etc.
  246. */
  247. GC_EXPORTX(int) gcWhatKind(void *p);
  248. /*
  249. * Return a pointer to the base (lowest address) of an object given
  250. * a pointer to a location within the object
  251. * Return 0 if displaced_pointer doesn't point to within a valid object.
  252. * gcIsValidPointer returns the start of the users area.
  253. * gcBase may point to debug information if present.
  254. */
  255. GC_EXPORTX(void *) gcIsValidPointer(const void * displaced_pointer);
  256. GC_EXPORTX(void *) gcBase(const void * displaced_pointer);
  257. /*
  258. * Check object with debugging info. Return kinds of
  259. * damage found as bit flags.
  260. * 1 User size smashed
  261. * 2 Start Flag smashed
  262. * 4 Near End flag smashed
  263. * 8 Far End flag smashed
  264. * 16 Previously freed.
  265. * 32 not a collectible object
  266. * 64 too small for a debug object od debug lib not used
  267. */
  268. GC_EXPORTX(int) gcObjectCheck(const void *ohdr);
  269. /*
  270. * Given a pointer into an object, return its size in bytes. gcFullSize
  271. * includes the debug header.
  272. */
  273. GC_EXPORTX(size_t) gcSize(const void * object_addr);
  274. GC_EXPORTX(size_t) gcFullSize(const void * object_addr);
  275. /*
  276. * A realloc()'ed object has the same collection kind as the original
  277. */
  278. GC_EXPORTX(void *) gcRealloc(void * old_object, size_t new_size_in_bytes);
  279. /*
  280. * Logging and diagnostic output.
  281. *
  282. * gcPrintf, gcErrorPrintf, gcWarningPrintf, gcAbort, gcReportLeak,
  283. * gcAbortPrintf and gcLogFileAbort all point at functions used for
  284. * various kinds of logging. The are initialized to point to functions
  285. * who`s names are gcDefaultPrintf, gcDefaultErrorPrintf etc.
  286. *
  287. * gcDefaultPrintf and gcDefaultErrorPrintf both print to the log file.
  288. *
  289. * gcDefaultWarningPrintf() only prints to the logfile if gcPrintStats
  290. * is nonzero. Otherwise it does nothing.
  291. *
  292. * gcDefaultAbortPrintf() formats a line and calls gcAbort.
  293. *
  294. * gcDefaultAbort() prints and exits.
  295. *
  296. * gcReportLeak() is used by the gcreport and gcreptdb libs to report
  297. * leaks. It's work is primarily done by gcPrintObj().
  298. *
  299. * If gcLogAllLeaks is nonzero, all leaks are reported to the log file.
  300. * If nonzero, only the first gcMaximumLeaksToLogFile are printed.
  301. *
  302. * void gcPuts() invokes via the function pointer gcPutsFunction which
  303. * defaults to gcDefaultPuts. In the threads libraries it locks and unlocks
  304. * the log file to prevent chaos. gcDefaultPuts discards calls made before
  305. * the collector is initialized.
  306. *
  307. * void gcDefaultPuts(const char *msg); writes to gcLogFile and insures it
  308. * is flushed every gcFlushLog lines. It is used by the above logging
  309. * functions. It may call gcLogFileAbort() which reports failures in using
  310. * gcLogFile and then aborts, hopefully a rare event. In GUI environment and
  311. * other situations, the user may wish to replace this. The function of
  312. * gcDefaultLogFileAbort is
  313. * sprintf(buf, "%s of %s failed.\n", msg, gcLogFile);
  314. * display buf somehow with the log file dead.
  315. * abort();
  316. */
  317. typedef void (* gcPrintFunction)(const char *, ...);
  318. typedef void (* gcPutFunction)(const char *msg);
  319. GC_EXPORTX(void) gcDefaultPrintf(const char *, ...);
  320. GC_EXPORTX(void) gcDefaultAbortPrintf(const char *, ...);
  321. GC_EXPORTX(void) gcDefaultWarningPrintf(const char *, ...);
  322. GC_EXPORTX(void) gcDefaultErrorPrintf(const char *, ...);
  323. GC_EXPORTX(void) gcDefaultAbort(const char *msg);
  324. GC_EXPORTX(void) gcPuts(const char *msg);
  325. GC_EXPORTX(void) gcDefaultPuts(const char *msg);
  326. GC_EXPORTX(void) gcDefaultLogFileAbort(const char *msg);
  327. GC_EXPORTX(void) gcDefaultReportLeak(const char *msg);
  328. GC_IMPORT gcPrintFunction gcPrintf, gcAbortPrintf, gcWarningPrintf,
  329. gcErrorPrintf;
  330. GC_IMPORT gcPutFunction gcAbort, gcLogFileAbort, gcReportLeak, gcPutsFunction;
  331. GC_IMPORT int gcLogAllLeaks;
  332. GC_IMPORT unsigned gcMaximumLeaksToLogFile;
  333. GC_IMPORT int gcGUIEnabled;
  334. /*
  335. * p points to somewhere inside an object.
  336. * Print a human readable description of the object using gcPrintf. If the
  337. * object has debugging information, this will all be printed as well.
  338. */
  339. GC_EXPORTX(void) gcPrintObject(const void *p);
  340. /*
  341. * Returns the debugging information
  342. */
  343. GC_EXPORTX(char *) gcDebugString(const void *p);
  344. GC_EXPORTX(int) gcDebugInt(const void *p);
  345. /*
  346. * Explicitly increase the heap size. Returns 0 on failure, 1 on success.
  347. * If you can use this to set your heap size to near its final value
  348. * your program will run more efficiently due to fewer collection cycles
  349. * and more efficient data structures. gcLogFile will show log when collector
  350. * expands the heap and how much. You may want to use gcNotTransparent
  351. * and gcSetMaxHeapSize() instead.
  352. */
  353. GC_EXPORTX(int) gcExpandHeap(size_t number_of_bytes);
  354. /*
  355. * Limit the heap size to n bytes. Useful when you're debugging
  356. * especially on systems that don't handle running out of memory well
  357. * n == 0 ==> unbounded. This is the default
  358. */
  359. GC_EXPORTX(void) gcSetMaxHeapSize(long n);
  360. /*
  361. * gcClearRoots clears the set of root segments.
  362. * gcAddRoots Adds a root segment.
  363. * gcDeclareLeafRoot declares all or part of a root segment as leaf.
  364. * All for wizards only.
  365. */
  366. GC_EXPORTX(void) gcClearRoots(NO_PARAMS);
  367. GC_EXPORTX(void) gcAddRoots(const char *low_address,
  368. const char *high_address_plus_1);
  369. GC_EXPORTX(void) gcDeclareLeafRoot(const char *low_address,
  370. const char *high_address_plus_1);
  371. /* Explicitly trigger a full, world-stop collection. */
  372. GC_EXPORTX(void) __cdecl gcCollect(NO_PARAMS);
  373. /*
  374. * Trigger a full world-stopped collection. Abort the collection if
  375. * and when stop_func returns a nonzero value. gcIdleTest will be
  376. * called frequently, and should be reasonably fast. This works even
  377. * if virtual dirty bits, and hence incremental collection is not
  378. * available for this architecture. Collections can be aborted faster
  379. * than normal pause times for incremental collection. However,
  380. * aborted collections do no useful work; the next collection needs
  381. * to start from the beginning.
  382. */
  383. typedef int (* gcIdleTestFunction)(NO_PARAMS);
  384. GC_EXPORTX(int) gcAttemptCollection(NO_PARAMS);
  385. /*
  386. * Explicitly trigger a full world-stop collection followed by
  387. * an explicit foot print reduce, or attempt to do so. Footprint
  388. * reduce wont free memory used since the last footprint reduce.
  389. * Normally this is correct but to do an extreme job call twice.
  390. */
  391. GC_EXPORTX(void) gcFootPrintReduce(NO_PARAMS);
  392. GC_EXPORTX(int) gcAttemptFootPrintReduce(NO_PARAMS);
  393. /*
  394. * In windows mode this defaults to gcMSWinIdleTest otherwise it
  395. * starts null and must be aimed by the user. Only used by gcAttemptCollection
  396. * and gcEnablePseudoIncremental.
  397. */
  398. GC_IMPORT gcIdleTestFunction gcIdleTest;
  399. /*
  400. * In Pseudo incremental mode Great Circle will periodically call
  401. * gcAttemptCollection();
  402. * in an attempt to free storage before increasing allocated heap.
  403. * There is actually a complex heuristic involved using the amount
  404. * allocated since the last collection and a few other things.
  405. */
  406. GC_EXPORTX(int) gcEnablePseudoIncremental(NO_PARAMS);
  407. GC_EXPORTX(int) gcDisablePseudoIncremental(NO_PARAMS);
  408. /*
  409. * gcNeverStopFunc can be used as a gcIdleTestFunction, gcAttemptCollection
  410. * recongizes it and is extra efficient.
  411. */
  412. GC_EXPORTX(int) gcNeverStopFunc(NO_PARAMS);
  413. /*
  414. * gcMSWinIdleTest is an idle test designed for the Windows environment.
  415. * It returns a 1 if there are windows events to process.
  416. */
  417. GC_EXPORTX(int) gcMSWinIdleTest(NO_PARAMS);
  418. /*
  419. * Return the number of bytes in the heap. Excludes collector private
  420. * data structures. Includes empty blocks and fragmentation loss.
  421. */
  422. GC_EXPORTX(size_t) gcGetHeapSize(NO_PARAMS);
  423. /* Return the number of bytes allocated since the last collection. */
  424. GC_EXPORTX(size_t) gcGetBytesSinceGc(NO_PARAMS);
  425. /*
  426. * Enable incremental/generational collection.
  427. * Don't use in leak finding mode.
  428. */
  429. GC_EXPORTX(void) gcEnableIncremental(NO_PARAMS);
  430. /*
  431. * Perform some garbage collection work, if appropriate.
  432. * Return 0 if there is no more work to be done.
  433. * Typically performs an amount of work corresponding roughly
  434. * to marking from one page. Does nothing if incremental collection is
  435. * disabled. It is reasonable to call this in a wait loop
  436. * until it returns 0. Returns 0 if not in incremental mode.
  437. */
  438. GC_EXPORTX(int) gcMinWork(NO_PARAMS);
  439. /*
  440. * This sets the scan alignment. gcSetScanAlignment(4) says all pointers
  441. * will be found on a 4 boundary. gcSetScanAlignment(1) says pointers may
  442. * be on any byte boundary. This returns True on success False on failure.
  443. * It hopefully defaults to the values used by the compiler to align pointers
  444. * and should not be reset unless you force pointers to odd boundaries.
  445. * This is checked to be 8, 4, 2 or 1 and minamum value.
  446. */
  447. GC_EXPORTX(int) gcSetScanAlignment(int align);
  448. /* Get current scan Alignment */
  449. GC_EXPORTX(int) gcGetScanAlignment(NO_PARAMS);
  450. /*
  451. * Debugging (annotated) allocation. gcCollect will check
  452. * objects allocated in this way for overwrites, etc. See
  453. * #ifdef GC_DEBUG at the end of this file.
  454. */
  455. GC_EXPORTX(void *) __cdecl gcMallocDebug(size_t size_in_bytes,
  456. const char * descr_string, int descr_int);
  457. GC_EXPORTX(void *) __cdecl gcMallocLeafDebug(size_t size_in_bytes,
  458. const char * descr_string, int descr_int);
  459. GC_EXPORTX(void *) __cdecl gcMallocIgnoreOffPageDebug(size_t size_in_bytes,
  460. const char * descr_string, int descr_int);
  461. GC_EXPORTX(void *) __cdecl gcMallocLeafIgnoreOffPageDebug(size_t size_in_bytes,
  462. const char * descr_string, int descr_int);
  463. GC_EXPORTX(void *) __cdecl gcMallocManualDebug(size_t size_in_bytes,
  464. const char * descr_string, int descr_int);
  465. GC_EXPORTX(void) __cdecl gcFreeDebug(void * object_addr);
  466. GC_EXPORTX(void *) __cdecl gcReallocDebug(void * old_object,
  467. size_t new_size_in_bytes,
  468. const char * descr_string, int descr_int);
  469. GC_EXPORTX(void *) __cdecl gcGlobalMallocDebug(size_t size,
  470. const char * descr_string,
  471. int lineNo);
  472. #define gcCalloc(size, num) gcMalloc((size) * (num))
  473. /*
  474. * Finalization. gcDeclareFinalizer[Offset] uses an ignore
  475. * selfpointers form required by C++. The Offset form is required by C++.
  476. * See the C++ section of this file for an example.
  477. * gcDeclareFinalizerNoPointers declares the finalized object has no pointers
  478. * to other objects that it requires at finalization time.
  479. */
  480. typedef void (* gcFinalizationProc)(void * obj);
  481. GC_EXPORTX(void) gcRegisterFinalizer(void * obj,
  482. gcFinalizationProc fn, void * cd);
  483. GC_EXPORTX(void) gcDeclareFinalizer(void * obj, gcFinalizationProc fn);
  484. GC_EXPORTX(void) gcDeclareFinalizerNoPointers(void * obj,
  485. gcFinalizationProc fn, void * cd);
  486. GC_EXPORTX(void) gcDeclareFinalizerOffset(void * obj,
  487. gcFinalizationProc fn, void * cd);
  488. /*
  489. * The following routine may be used to break cycles between
  490. * finalizable objects, thus causing cyclic finalizable
  491. * objects to be finalized in the correct order. Standard
  492. * use involves calling gcPtrNotUsedByFinalizer(&p)
  493. * where p is a pointer that is not used by finalization
  494. * code, and should not be considered in determining
  495. * finalization order.
  496. */
  497. GC_EXPORTX(int) gcPtrNotUsedByFinalizer(void **link);
  498. /*
  499. * If you have called gcDisappearingPtr(link, obj), then *link
  500. * will be automatically zeroed when the data pointed to by
  501. * obj becomes inaccessible. This will happen before any finalization
  502. * occurs.
  503. *
  504. * Returns 1 if link was already registered, 0 otherwise.
  505. *
  506. * gcDisappearingPtr is often used when implementing weak pointers
  507. * (pointers that are not traced during collection). By ensuring that
  508. * the weak pointer is zeroed if the data it is pointing to goes away,
  509. * the danger of following a loose weak pointer is eliminated.
  510. *
  511. * In this case, have link point to a location holding
  512. * a disguised pointer to obj. (A pointer inside a "leaf"
  513. * object is efficiently disguised.) The pointer is zeroed
  514. * when obj becomes inaccessible. Each link may be registered only
  515. * once. However, it should be unregistered and reregistered if
  516. * the pointer is modified to point at a differenct object.
  517. *
  518. * Note that obj may be resurrected by another finalizer.
  519. */
  520. GC_EXPORTX(int) gcDisappearingPtr(void ** link, void * obj);
  521. GC_EXPORTX(int) gcUnregisterDisappearingPtr(void ** link);
  522. /*
  523. * Converting a hidden pointer to a real pointer requires verifying
  524. * that the object still exists. This involves acquiring the
  525. * allocator lock to avoid a race with the collector.
  526. */
  527. typedef void * (*gcFnType)(void *);
  528. GC_EXPORTX(void *) gcCallWithAllocLock(gcFnType fn, void * client_data);
  529. /*
  530. * If p and q point to the same object returns p else calls gcAbort()
  531. * Succeeds if neither p nor q points to the heap.
  532. */
  533. GC_EXPORTX(void *) gcSameObj(void *p, void *q);
  534. GC_EXPORTX(void) gcSetDirty(void *);
  535. GC_EXPORTX(int) gcInSameObj(void *, void *);
  536. /*
  537. * Safer, but slow, pointer addition. Probably useful mainly with
  538. * a preprocessor. Useful only for heap pointers.
  539. */
  540. #ifdef GC_DEBUG_BOUNDS_CHECK
  541. # define GC_PTR_ADD(x, n) ((gcSameObj((void *)((x)+(n)), (void *)(x))), ((x)+(n)))
  542. #else /* !GC_DEBUG_BOUNDS_CHECK */
  543. # define GC_PTR_ADD(x, n) ((x)+(n))
  544. #endif
  545. /* Safer assignment of a pointer to a nonstack location. */
  546. #ifdef GC_DEBUG_BOUNDS_CHECK
  547. # define GC_PTR_STORE(p, q) \
  548. (*(void **)gcIsVisible(p) = gcIsValidDisplacement(q))
  549. #else /* !GC_DEBUG_BOUNDS_CHECK */
  550. # define GC_PTR_STORE(p, q) *((p) = (q))
  551. #endif
  552. /*
  553. * gcHidePointer takes a pointer and flips its bits so Great Circle
  554. * wont recognise it as a pointer. gcRevealPointer flips them back.
  555. */
  556. # define gcHidePointer(p) (~(gcWord)(p))
  557. # define gcRevealPointer(p) ((void *)(gcHidePointer(p)))
  558. /*
  559. * Under Windows there are operating system calls to get memory
  560. * (Global|Local)|(Alloc|ReAlloc). By default, we pass these calls
  561. * on to Windows, although we still scan such memory for pointers.
  562. * You can redefine this behavior in your gcInitialize() function
  563. * by settin gcAllocBehavior to GC_INTERCEPT. In this case, Great
  564. * Circle will garbage collect memory allocated by (Global|Local)|(Alloc|ReAlloc)
  565. * except when allocated with the (GMEM|LMEM)_(MOVEABLE|DISCARDABLE) flags.
  566. */
  567. #define GC_INTERCEPT 0 /* intercept calls */
  568. #define GC_PASS_THROUGH 1 /* DEFAULT: pass through calls trace */
  569. /* their results. */
  570. #define GC_TRACE_ALL 2 /* pass through calls trace their results */
  571. /* on a per-object basis. */
  572. GC_IMPORT int gcAllocBehavior;
  573. GC_IMPORT int gcAllocWarn; /* warnings for (Global|Local)|(Alloc|ReAlloc) */
  574. GC_EXPORTX(const char *) gcGetDllName();
  575. GC_IMPORT int gcDontInterceptCRunTimeDLL;
  576. /*
  577. * Allocates a page, generally 4K, of objects and returns them as a list
  578. * linked through their first word. Its use can greatly reduce lock
  579. * contention problems in threaded systems, since the allocation lock
  580. * can be acquired and released many fewer times. In unthreaded systems
  581. * this is pointless. These are always non debug objects.
  582. */
  583. GC_EXPORTX(void *) gcMallocMany(size_t lb);
  584. /* Retrive the next item in list reutrned by gcMallocMany */
  585. #define GC_NEXT(p) (*(void **)(p))
  586. # define GC_INIT()
  587. /*
  588. * Call to register root segments.
  589. */
  590. GC_EXPORTX(void) gcRegisterDLL(char * static_root);
  591. /* these are used to identify the library used */
  592. GC_EXPORTX(const char *) gcLibrary(NO_PARAMS); /* gcall etc */
  593. GC_EXPORTX(const char *) gcCompiler(NO_PARAMS); /* compiler used */
  594. GC_EXPORTX(int) gcVersion(NO_PARAMS); /* version number * 100, 1.1 -> 110 */
  595. GC_EXPORTX(int) gcBuildNo(NO_PARAMS); /* Build number */
  596. GC_EXPORTX(int) gcThreads(NO_PARAMS); /* 1 if thread safe 0 otherwise */
  597. GC_EXPORTX(long) gcEvaluationCopy(); /* Returns non zero for eval copies */
  598. /*
  599. * gcFreeX is exactly like free but has a consistent interface.
  600. * some systems have a free that cleverly returns an int.
  601. */
  602. GC_EXPORTX(void) gcFreeX(void *);
  603. enum gcNewType {
  604. gcMemDefault = 0, /* don't change threads code uses values */
  605. gcMemAuto = 1,
  606. gcMemLeaf = 2,
  607. gcMemManual = 3,
  608. gcMemAutoIgn = 4,
  609. gcMemLeafIgn = 5
  610. };
  611. #ifdef __cplusplus
  612. } /* end of extern "C" */
  613. /* C++ Interface to GCTransparent */
  614. # include <new.h>
  615. #define gcSetDirty(x)
  616. #define GC_CLASS_HAS_POINTERS \
  617. void * operator new(size_t s) { return gcNewDefaultAuto(s); } \
  618. void * operator new(size_t s, char *f, int l) \
  619. { return gcNewDefaultAuto(s, f, l); } \
  620. void operator delete( void* obj ) { gcFreeX(obj); }
  621. #define GC_CLASS_HAS_NO_POINTERS \
  622. void * operator new(size_t s) { return gcNewDefaultLeaf(s); } \
  623. void * operator new(size_t s, char *f, int l) \
  624. { return gcNewDefaultLeaf(s, f, l); } \
  625. void operator delete( void* obj ) { gcFreeX(obj); }
  626. #define GC_CLASS_IS_MANUAL \
  627. void * operator new(size_t s) { return gcNewDefaultManual(s); } \
  628. void * operator new(size_t s, char *f, int l) \
  629. { return gcNewDefaultManual(s, f, l); } \
  630. void operator delete( void* obj ) { gcFreeX(obj); }
  631. GC_EXPORTX(void *) gcNewDefaultAuto(size_t s);
  632. GC_EXPORTX(void *) gcNewDefaultAuto(size_t s, const char *file, int line);
  633. GC_EXPORTX(void *) gcNewDefaultLeaf(size_t s);
  634. GC_EXPORTX(void *) gcNewDefaultLeaf(size_t s, const char *file, int line);
  635. GC_EXPORTX(void *) gcNewDefaultManual(size_t s);
  636. GC_EXPORTX(void *) gcNewDefaultManual(size_t s, const char *file, int line);
  637. GC_EXPORTY(void *) __cdecl operator new(size_t size);
  638. GC_EXPORTY(void *) __cdecl operator new(size_t size, const char *file, int line);
  639. GC_EXPORTY(void) __cdecl operator delete(void *);
  640. /*
  641. * Instances of classes derived from "gc" will be allocated in the
  642. * collected heap by default, unless an explicit placement is
  643. * specified.
  644. */
  645. GC_EXPORTY(class) gc {
  646. public:
  647. GC_CLASS_HAS_POINTERS
  648. void* operator new(size_t, void *p) { return p; }
  649. };
  650. extern "C" {
  651. GC_EXPORTX(void) gcSetAllocator(gcNewType);
  652. }
  653. #define GC_NEW(x) (gcSetAllocator(gcMemAuto), new x)
  654. #define GC_NEW_LEAF(x) (gcSetAllocator(gcMemLeaf), new x)
  655. #define GC_NEW_MANUAL(x) (gcSetAllocator(gcMemManual), new x)
  656. #define GC_NEW_IGNORE_OFF_PAGE(x) (gcSetAllocator(gcMemAutoIgn), new x)
  657. #define GC_NEW_LEAF_IGNORE_OFF_PAGE(x) (gcSetAllocator(gcMemLeafIgn), new x)
  658. #define GC_NEW_ARRAY(s, t) \
  659. (new gcArrayBase(GC_NEW(t[s]), s, sizeof(t)))
  660. #define GC_NEW_LEAF_ARRAY(s, t) \
  661. (new gcArrayBase(GC_NEW_LEAF(t[s]), s, sizeof(t)))
  662. #define GC_NEW_MANUAL_ARRAY(s, t) \
  663. (new gcArrayBase(GC_NEW_MANUAL(t[s]), s, sizeof(t)))
  664. #define GC_NEW_LEAF_IGNORE_OFF_PAGE_ARRAY(s, t) \
  665. (new gcArrayBase(GC_NEW_LEAF_IGNORE_OFF_PAGE(t[s]), s, sizeof(t)))
  666. #define GC_NEW_IGNORE_OFF_PAGE_ARRAY(s, t) \
  667. (new gcArrayBase(GC_NEW_IGNORE_OFF_PAGE(t[s]), s, sizeof(t)))
  668. /*
  669. * Class gcLWCleanup behaves like gcCleanup except that it does not inherit
  670. * from class gc. Therefore, you must be sure that your class is being
  671. * allocated as garbage collected (e.g. if you are using the gcall library).
  672. * gcLWCleanup is useful when private inheritance is making class gc's
  673. * operator new inaccessible.
  674. */
  675. GC_EXPORTY(class) gcLWCleanup {
  676. public:
  677. inline gcLWCleanup();
  678. inline virtual ~gcLWCleanup();
  679. private:
  680. inline static void cleanup( void* obj );
  681. };
  682. class gcCleanup: virtual public gc, virtual public gcLWCleanup {};
  683. /*
  684. * Instances of classes derived from "gcCleanup" will be allocated
  685. * in the collected heap by default. When the collector discovers an
  686. * inaccessible object derived from "gcCleanup" or containing a
  687. * member derived from "gcCleanup", its destructors will be
  688. * invoked.
  689. */
  690. inline gcLWCleanup::~gcLWCleanup() {
  691. gcDeclareFinalizer(this, 0);
  692. }
  693. inline void gcLWCleanup::cleanup( void* obj ) {
  694. ((gcLWCleanup*)obj)->~gcLWCleanup();
  695. }
  696. inline gcLWCleanup::gcLWCleanup() {
  697. void* base;
  698. if (0 != (base = gcBase((void *)this)))
  699. gcDeclareFinalizerOffset(base,
  700. (gcFinalizationProc)cleanup,
  701. (void*)this);
  702. }
  703. #include <assert.h>
  704. #define GC_TEMPLATE template<class T>
  705. #ifndef GC_DEBUG
  706. #define GC_ASSERT(cond, message)
  707. #else
  708. #define GC_ASSERT(cond, message) if (!(cond)) \
  709. gcErrorPrintf("%s\n", message);
  710. #endif
  711. /* Parent for wrapped data pointers and references. */
  712. template<class T>
  713. class gcWrap {
  714. public:
  715. int gcPtrNotUsedByFinalizer() {
  716. return ::gcPtrNotUsedByFinalizer((void **)&data);
  717. }
  718. protected:
  719. gcWrap() {
  720. setPointer();
  721. }
  722. gcWrap(T *p) {
  723. setPointer(p);
  724. }
  725. gcWrap(const gcWrap< T > &p) {
  726. setPointer(p);
  727. }
  728. /* This exists because stack frames may not be zeroed. */
  729. ~gcWrap() {
  730. setPointer();
  731. }
  732. void dirtyPointer() {
  733. gcSetDirty(&data);
  734. }
  735. void setPointer() {
  736. data = 0;
  737. }
  738. void setPointer(T* p) {
  739. dirtyPointer();
  740. data = p;
  741. }
  742. void setPointer(const gcWrap< T > &p) {
  743. dirtyPointer();
  744. data = p.data;
  745. }
  746. T* data; /* The pointer to the actual object */
  747. };
  748. template<class T>
  749. class gcPtr : public gcWrap<T> {
  750. public:
  751. gcPtr() {}
  752. gcPtr(T *p) : gcWrap<T>(p) {}
  753. gcPtr(const gcPtr< T > &p) : gcWrap<T>(p) {}
  754. T* operator=(T *x) {
  755. setPointer(x);
  756. return data;
  757. }
  758. T* operator=(const gcPtr< T > &x) {
  759. setPointer(x);
  760. return data;
  761. }
  762. operator T*() const {
  763. return data;
  764. }
  765. operator void*() const {
  766. return (void *)data;
  767. }
  768. T* operator()() const {
  769. return data;
  770. }
  771. T* operator->() const {
  772. return data;
  773. }
  774. int operator!() const {
  775. return data == 0;
  776. }
  777. int operator==(const gcPtr< T > &x) const {
  778. return data == x.data;
  779. }
  780. int operator==(T *x) const {
  781. return data == x;
  782. }
  783. int operator!=(const gcPtr< T > &x) const {
  784. return data != x.data;
  785. }
  786. int operator!=(T *x) const {
  787. return data != x;
  788. }
  789. T& operator[](int n) const;
  790. T* operator+(int n) const;
  791. T* operator-(int n) const;
  792. T* operator+=(int n);
  793. T* operator-=(int n);
  794. #ifdef GC_DEBUG_BOUNDS_CHECK
  795. T* operator=(int n) {
  796. GC_ASSERT(!n, "Invalid integer to pointer assignment");
  797. setPointer();
  798. return 0;
  799. }
  800. T& operator*() const {
  801. GC_ASSERT(data, "Dereference of null pointer");
  802. return *data;
  803. }
  804. #else
  805. T* operator=(int) {
  806. setPointer();
  807. return 0;
  808. }
  809. T& operator*() const { return *data; }
  810. #endif
  811. };
  812. template<class T>
  813. inline T& gcPtr<T>::operator[]( int n ) const {
  814. return *(data + n);
  815. }
  816. template<class T>
  817. inline T* gcPtr<T>::operator+(int n) const {
  818. return data + n;
  819. }
  820. template<class T>
  821. inline T* gcPtr<T>::operator-(int n) const {
  822. return data - n;
  823. }
  824. template<class T>
  825. inline T* gcPtr<T>::operator+=(int n) {
  826. return data = (data + n);
  827. }
  828. template<class T>
  829. inline T* gcPtr<T>::operator-=(int n) {
  830. return data = (data - n);
  831. }
  832. template<class T>
  833. class gcRef : public gcWrap<T> {
  834. gcRef() {}
  835. gcRef(const T &x) : gcWrap<T>((T *)&x) {}
  836. gcRef(const gcRef< T > &x) : gcWrap<T>(x) {}
  837. /* The next two operators may not inline right */
  838. void operator=(T &x) {
  839. *data = x;
  840. }
  841. void operator=(const gcRef< T > &x) {
  842. *data = x();
  843. x.dirtyPointer();
  844. }
  845. T& operator()() const {
  846. return *data;
  847. }
  848. operator T&() const {
  849. return *data;
  850. }
  851. };
  852. /* Return values for gcInBounds tests */
  853. enum gcArrayTest {
  854. gcNotAnArray,
  855. gcPointerOk,
  856. gcPointerTooLow,
  857. gcPointerTooHigh,
  858. gcPointerAtEnd
  859. };
  860. /* Parent of all array class templates. */
  861. class gcArrayBase : public gc {
  862. public:
  863. gcArrayBase(void *array, size_t count, size_t size) :
  864. gcData(array), gcCount(count), gcItemLen(size) {}
  865. operator void *() const {
  866. return gcData;
  867. }
  868. size_t size() const {
  869. return gcCount * gcItemLen;
  870. }
  871. void * gcArrayTop() const {
  872. return (char *)gcData + size();
  873. }
  874. size_t len() const {
  875. return gcCount;
  876. }
  877. void setLen(size_t newLen) {
  878. GC_ASSERT((gcCount >= newLen), "Array length set too long");
  879. gcCount = newLen;
  880. }
  881. int gcValidReference(const void *p) {
  882. return p < gcArrayTop() && p >= (void *)*this;
  883. }
  884. void * operator +(size_t x) {
  885. return (char *)(void *)*this + (x * gcItemLen);
  886. }
  887. gcArrayTest gcInBounds(const void *newP) const {
  888. gcArrayTest ii = ( gcArrayTest ) 0;
  889. if ((unsigned long)newP < (unsigned long)(void *)*this)
  890. ii = gcPointerTooLow;
  891. if ((unsigned long)newP > (unsigned long)gcArrayTop())
  892. ii = gcPointerTooHigh;
  893. if (!ii)
  894. ii = (newP == gcArrayTop()) ? gcPointerAtEnd : gcPointerOk;
  895. return ii;
  896. }
  897. private:
  898. void *gcData;
  899. size_t gcCount, gcItemLen;
  900. };
  901. template<class T>
  902. class gcArrayPtr {
  903. protected:
  904. T *data; /* Pointer to array item */
  905. gcArrayBase * array; /* The pointer to the actual array base or zero */
  906. void dirtyPointer() {
  907. gcSetDirty(&data);
  908. }
  909. void setPointer() {
  910. data = 0;
  911. array = 0;
  912. }
  913. void setPointer(T* p) {
  914. dirtyPointer();
  915. data = p;
  916. array = 0;
  917. }
  918. void setPointer(const gcArrayPtr< T > &p) {
  919. dirtyPointer();
  920. data = p.data;
  921. array = p.array;
  922. }
  923. void setPointer(gcArrayBase *p) {
  924. dirtyPointer();
  925. data = (T*)(void *)*p;
  926. array = p;
  927. }
  928. public:
  929. gcArrayPtr() {
  930. setPointer();
  931. }
  932. gcArrayPtr(T *p) {
  933. setPointer(p);
  934. }
  935. gcArrayPtr(const gcArrayPtr< T > &p) {
  936. setPointer(p);
  937. }
  938. gcArrayPtr(gcArrayBase *p) {
  939. setPointer(p);
  940. }
  941. int gcPtrNotUsedByFinalizer() {
  942. ::gcPtrNotUsedByFinalizer((void **)&array);
  943. return ::gcPtrNotUsedByFinalizer((void **)&data);
  944. }
  945. T* operator=(gcArrayBase *x) {
  946. setPointer(x);
  947. return data;
  948. }
  949. T* operator=(T *x) {
  950. array = 0;
  951. setPointer(x);
  952. return data;
  953. }
  954. T* operator=(const gcArrayPtr< T > &x) {
  955. setPointer(x);
  956. return data;
  957. }
  958. operator void*() const {
  959. return (void *)data;
  960. }
  961. T* operator()() const {
  962. return data;
  963. }
  964. int operator!() const {
  965. return data == 0;
  966. }
  967. int operator==(const gcArrayPtr< T > &x) const {
  968. return data == x.data;
  969. }
  970. int operator==(T *x) const {
  971. return data == x;
  972. }
  973. int operator!=(const gcArrayPtr< T > &x) const {
  974. return data != x.data;
  975. }
  976. int operator!=(T *x) const {
  977. return data != x;
  978. }
  979. T* operator+(int n) const {
  980. return data + n;
  981. }
  982. T* operator-(int n) const {
  983. return (*this) + -n;
  984. }
  985. T* operator+=(int n) {
  986. return data = (*this + n);
  987. }
  988. T* operator-=(int n) {
  989. return data = (*this + -n);
  990. }
  991. size_t len() const {
  992. return array ? array->len() : 0;
  993. }
  994. size_t size() const {
  995. return array ? array->size() : 0;
  996. }
  997. void setLen(size_t l) {
  998. if (array)
  999. array->setLen(l);
  1000. }
  1001. #ifdef GC_DEBUG_BOUNDS_CHECK
  1002. T* operator=(int n) {
  1003. GC_ASSERT(!n, "Invalid integer to pointer assignment");
  1004. setPointer();
  1005. return 0;
  1006. }
  1007. T& operator[](int n) {
  1008. GC_ASSERT(array->gcValidReference((void *)(data + n)),
  1009. "Invalid array reference");
  1010. return *(*this + n);
  1011. }
  1012. T& operator *() const {
  1013. GC_ASSERT(array->gcValidReference((void *)data),
  1014. "Invalid array pointer dereferenced");
  1015. return *data;
  1016. }
  1017. #else
  1018. T* operator=(int) {
  1019. setPointer();
  1020. return 0;
  1021. }
  1022. T& operator*() const {
  1023. return *data;
  1024. }
  1025. T& operator[](int n) {
  1026. return *(*this + n);
  1027. }
  1028. #endif
  1029. gcArrayTest gcInObject(void *loc) const {
  1030. gcArrayTest ii = ( gcArrayTest ) 0;
  1031. if (!data)
  1032. ii = gcNotAnArray;
  1033. else if (array) {
  1034. if (loc < (void *)*array)
  1035. ii = gcPointerTooLow;
  1036. else if (loc > array->gcArrayTop())
  1037. ii = gcPointerTooHigh;
  1038. else if (loc == array->gcArrayTop())
  1039. ii = gcPointerAtEnd;
  1040. else
  1041. ii = gcPointerOk;
  1042. }
  1043. else if (gcInSameObj((void *)data, (void *)loc))
  1044. ii = gcPointerOk;
  1045. else
  1046. ii = ((void *)loc > (void *)data) ? gcPointerTooHigh : gcPointerTooLow;
  1047. return (ii);
  1048. }
  1049. gcArrayTest gcInBounds(int n) const {
  1050. return gcInObject(data + n);
  1051. }
  1052. };
  1053. #endif /* __cplusplus */
  1054. # ifdef GC_DEBUG_LINE_NUMBERS
  1055. # define malloc(sz) gcGlobalMallocDebug((sz), __FILE__, __LINE__)
  1056. # define calloc(sz, cnt) gcGlobalMallocDebug((sz)*(cnt), __FILE__, __LINE__)
  1057. # define gcMalloc(sz) gcMallocDebug((sz), __FILE__, __LINE__)
  1058. # define gcMallocLeaf(sz) gcMallocLeafDebug((sz), __FILE__, __LINE__)
  1059. # define gcMallocIgnoreOffPage(sz) gcMallocIgnoreOffPageDebug((sz), __FILE__, __LINE__)
  1060. # define gcMallocLeafIgnoreOffPage(sz) gcMallocLeafIgnoreOffPageDebug((sz), __FILE__, __LINE__)
  1061. # define gcMallocManual(sz) gcMallocManualDebug((sz), \
  1062. __FILE__, __LINE__)
  1063. # define gcRealloc(old, sz) gcReallocDebug((old), (sz), __FILE__, \
  1064. __LINE__)
  1065. # define realloc(old, sz) gcReallocDebug((old), (sz), __FILE__, \
  1066. __LINE__)
  1067. # define gcFree(p) gcFreeDebug(p)
  1068. # endif
  1069. #endif /* _GCT_H */