fnlz_mlc.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved.
  3. *
  4. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  6. *
  7. * Permission is hereby granted to use or copy this program
  8. * for any purpose, provided the above notices are retained on all copies.
  9. * Permission to modify the code and to distribute modified code is granted,
  10. * provided the above notices are retained, and a notice that the code was
  11. * modified is included with the above copyright notice.
  12. *
  13. */
  14. #include "private/gc_priv.h"
  15. #ifdef ENABLE_DISCLAIM
  16. #include "gc/gc_disclaim.h"
  17. #include "private/dbg_mlc.h" /* for oh type */
  18. #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
  19. /* The first bit is already used for a debug purpose. */
  20. # define FINALIZER_CLOSURE_FLAG 0x2
  21. #else
  22. # define FINALIZER_CLOSURE_FLAG 0x1
  23. #endif
  24. STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
  25. {
  26. # ifdef AO_HAVE_load
  27. word fc_word = (word)AO_load((volatile AO_t *)obj);
  28. # else
  29. word fc_word = *(word *)obj;
  30. # endif
  31. if ((fc_word & FINALIZER_CLOSURE_FLAG) != 0) {
  32. /* The disclaim function may be passed fragments from the */
  33. /* free-list, on which it should not run finalization. */
  34. /* To recognize this case, we use the fact that the first word */
  35. /* on such fragments is always multiple of 4 (a link to the next */
  36. /* fragment, or NULL). If it is desirable to have a finalizer */
  37. /* which does not use the first word for storing finalization */
  38. /* info, GC_reclaim_with_finalization must be extended to clear */
  39. /* fragments so that the assumption holds for the selected word. */
  40. const struct GC_finalizer_closure *fc
  41. = (struct GC_finalizer_closure *)(fc_word
  42. & ~(word)FINALIZER_CLOSURE_FLAG);
  43. GC_ASSERT(!GC_find_leak);
  44. (*fc->proc)((word *)obj + 1, fc->cd);
  45. }
  46. return 0;
  47. }
  48. GC_API void GC_CALL GC_init_finalized_malloc(void)
  49. {
  50. DCL_LOCK_STATE;
  51. GC_init(); /* In case it's not already done. */
  52. LOCK();
  53. if (GC_finalized_kind != 0) {
  54. UNLOCK();
  55. return;
  56. }
  57. /* The finalizer closure is placed in the first word in order to */
  58. /* use the lower bits to distinguish live objects from objects on */
  59. /* the free list. The downside of this is that we need one-word */
  60. /* offset interior pointers, and that GC_base does not return the */
  61. /* start of the user region. */
  62. GC_register_displacement_inner(sizeof(word));
  63. /* And, the pointer to the finalizer closure object itself is */
  64. /* displaced due to baking in this indicator. */
  65. GC_register_displacement_inner(FINALIZER_CLOSURE_FLAG);
  66. GC_register_displacement_inner(sizeof(oh) + FINALIZER_CLOSURE_FLAG);
  67. GC_finalized_kind = GC_new_kind_inner(GC_new_free_list_inner(),
  68. GC_DS_LENGTH, TRUE, TRUE);
  69. GC_ASSERT(GC_finalized_kind != 0);
  70. GC_register_disclaim_proc(GC_finalized_kind, GC_finalized_disclaim, TRUE);
  71. UNLOCK();
  72. }
  73. GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
  74. int mark_unconditionally)
  75. {
  76. GC_ASSERT((unsigned)kind < MAXOBJKINDS);
  77. GC_ASSERT(NONNULL_ARG_NOT_NULL(proc));
  78. if (!EXPECT(GC_find_leak, FALSE)) {
  79. GC_obj_kinds[kind].ok_disclaim_proc = proc;
  80. GC_obj_kinds[kind].ok_mark_unconditionally =
  81. (GC_bool)mark_unconditionally;
  82. }
  83. }
  84. GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb,
  85. const struct GC_finalizer_closure *fclos)
  86. {
  87. void *op;
  88. GC_ASSERT(GC_finalized_kind != 0);
  89. GC_ASSERT(NONNULL_ARG_NOT_NULL(fclos));
  90. GC_ASSERT(((word)fclos & FINALIZER_CLOSURE_FLAG) == 0);
  91. op = GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(word)), GC_finalized_kind);
  92. if (EXPECT(NULL == op, FALSE))
  93. return NULL;
  94. # ifdef AO_HAVE_store
  95. AO_store((volatile AO_t *)op, (AO_t)fclos | FINALIZER_CLOSURE_FLAG);
  96. # else
  97. *(word *)op = (word)fclos | FINALIZER_CLOSURE_FLAG;
  98. # endif
  99. GC_dirty(op);
  100. REACHABLE_AFTER_DIRTY(fclos);
  101. return (word *)op + 1;
  102. }
  103. #endif /* ENABLE_DISCLAIM */