Exemple #1
0
void GC_notify_or_invoke_finalizers(void)
{
    /* This is a convenient place to generate backtraces if appropriate, */
    /* since that code is not callable with the allocation lock.	 */
#   if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
      static word last_back_trace_gc_no = 1;	/* Skip first one. */

      if (GC_gc_no > last_back_trace_gc_no) {
	word i;
  
#	ifdef KEEP_BACK_PTRS
	  LOCK();
  	  /* Stops when GC_gc_no wraps; that's OK.	*/
	  last_back_trace_gc_no = (word)(-1);  /* disable others. */
	  for (i = 0; i < GC_backtraces; ++i) {
	      /* FIXME: This tolerates concurrent heap mutation,	*/
	      /* which may cause occasional mysterious results.		*/
	      /* We need to release the GC lock, since GC_print_callers	*/
	      /* acquires it.  It probably shouldn't.			*/
	      UNLOCK();
	      GC_generate_random_backtrace_no_gc();
	      LOCK();
	  }
	  last_back_trace_gc_no = GC_gc_no;
	  UNLOCK();
#	endif
#       ifdef MAKE_BACK_GRAPH
	  if (GC_print_back_height)
            GC_print_back_graph_stats();
#	endif
      }
#   endif
    if (GC_finalize_now == 0) return;
    if (!GC_finalize_on_demand) {
	(void) GC_invoke_finalizers();
#	ifndef THREADS
	  GC_ASSERT(GC_finalize_now == 0);
#	endif	/* Otherwise GC can run concurrently and add more */
	return;
    }
    if (GC_finalizer_notifier != (void (*) (void))0
	&& last_finalizer_notification != GC_gc_no) {
	last_finalizer_notification = GC_gc_no;
	GC_finalizer_notifier();
    }
}
Exemple #2
0
GC_INNER void GC_notify_or_invoke_finalizers(void)
{
    GC_finalizer_notifier_proc notifier_fn = 0;
#   if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
      static word last_back_trace_gc_no = 1;    /* Skip first one. */
#   endif
    DCL_LOCK_STATE;

#   if defined(THREADS) && !defined(KEEP_BACK_PTRS) \
       && !defined(MAKE_BACK_GRAPH)
      /* Quick check (while unlocked) for an empty finalization queue.  */
      if (NULL == GC_fnlz_roots.finalize_now) return;
#   endif
    LOCK();

    /* This is a convenient place to generate backtraces if appropriate, */
    /* since that code is not callable with the allocation lock.         */
#   if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
      if (GC_gc_no > last_back_trace_gc_no) {
#       ifdef KEEP_BACK_PTRS
          long i;
          /* Stops when GC_gc_no wraps; that's OK.      */
          last_back_trace_gc_no = (word)(-1);  /* disable others. */
          for (i = 0; i < GC_backtraces; ++i) {
              /* FIXME: This tolerates concurrent heap mutation,        */
              /* which may cause occasional mysterious results.         */
              /* We need to release the GC lock, since GC_print_callers */
              /* acquires it.  It probably shouldn't.                   */
              UNLOCK();
              GC_generate_random_backtrace_no_gc();
              LOCK();
          }
          last_back_trace_gc_no = GC_gc_no;
#       endif
#       ifdef MAKE_BACK_GRAPH
          if (GC_print_back_height) {
            UNLOCK();
            GC_print_back_graph_stats();
            LOCK();
          }
#       endif
      }
#   endif
    if (NULL == GC_fnlz_roots.finalize_now) {
      UNLOCK();
      return;
    }

    if (!GC_finalize_on_demand) {
      unsigned char *pnested = GC_check_finalizer_nested();
      UNLOCK();
      /* Skip GC_invoke_finalizers() if nested */
      if (pnested != NULL) {
        (void) GC_invoke_finalizers();
        *pnested = 0; /* Reset since no more finalizers. */
#       ifndef THREADS
          GC_ASSERT(NULL == GC_fnlz_roots.finalize_now);
#       endif   /* Otherwise GC can run concurrently and add more */
      }
      return;
    }

    /* These variables require synchronization to avoid data races.     */
    if (last_finalizer_notification != GC_gc_no) {
        last_finalizer_notification = GC_gc_no;
        notifier_fn = GC_finalizer_notifier;
    }
    UNLOCK();
    if (notifier_fn != 0)
        (*notifier_fn)(); /* Invoke the notifier */
}