예제 #1
0
int
scm_run_finalizers (void)
{
  int finalized = GC_invoke_finalizers ();

  finalization_count += finalized;

  return finalized;
}
JAVA_INT org_xmlvm_runtime_FinalizerNotifier_invokeFinalizers__()
{
    //XMLVM_BEGIN_NATIVE[org_xmlvm_runtime_FinalizerNotifier_invokeFinalizers__]
#ifndef XMLVM_NO_GC
    return GC_invoke_finalizers();
#else
    return 0;
#endif
    //XMLVM_END_NATIVE
}
예제 #3
0
파일: boehm-gc.c 프로젝트: Sciumo/mono
int
mono_gc_invoke_finalizers (void)
{
	/* There is a bug in GC_invoke_finalizer () in versions <= 6.2alpha4:
	 * the 'mem_freed' variable is not initialized when there are no
	 * objects to finalize, which leads to strange behavior later on.
	 * The check is necessary to work around that bug.
	 */
	if (GC_should_invoke_finalizers ())
		return GC_invoke_finalizers ();
	return 0;
}
예제 #4
0
/*
 *	Main entry point for the finalizer thread.
 */
static void _FinalizerThreadFunc(void *data)
{
	GC_TRACE("GC:_FinalizerThread: Finalizer thread started [thread:%d]\n", (int)ILThreadSelf());

	for (;;)
	{
		ILWaitOne(_FinalizerSignal, -1);

		GC_TRACE("GC:_FinalizerThread: Signal [thread:%d]\n", (int)ILThreadSelf());

		/* This *must* to be set before checking for !_FinalizersDisabled to prevent
		    a race with ILGCDisableFinalizers */

		_FinalizersRunning = 1;

		ILThreadMemoryBarrier();

		if (GC_should_invoke_finalizers() && !_FinalizersDisabled)
		{
			GC_TRACE("GC:_FinalizerThread: Finalizers running [thread:%d]\n", (int)ILThreadSelf());
			
			GC_invoke_finalizers();
			
			GC_TRACE("GC:_FinalizerThread: Finalizers finished [thread:%d]\n", (int)ILThreadSelf());
		}

		_FinalizersRunning = 0;

		ILThreadMemoryBarrier();
		
		if (_FinalizerStopFlag)
		{
			/* Exit finalizer thread after having invoked finalizers one last time */

			GC_TRACE("GC:_FinalizerThread: Finalizer thread finished [thread:%d]\n", (int)ILThreadSelf());

			ILWaitEventReset(_FinalizerSignal);
			/* Wake all waiting threads */
			ILWaitEventPulse(_FinalizerResponse);
			
			return;
		}

		GC_TRACE("GC:_FinalizerThread: Response [thread:%d]\n", (int)ILThreadSelf());

		ILWaitEventReset(_FinalizerSignal);

		/* Wake all waiting threads */
		ILWaitEventPulse(_FinalizerResponse);
	}
}
예제 #5
0
void boehm_gc_finalizer_notifier(void)
{
    boehm_gc_finalizer_lock++;
    while (GC_should_invoke_finalizers()) {
        if (boehm_gc_finalizer_lock > 1) {
            /* GC_invoke_finalizers() will be done by the
               boehm_gc_finalizer_notifier() that is
               currently in the C stack, when we return there */
            break;
        }
        GC_invoke_finalizers();
    }
    boehm_gc_finalizer_lock--;
}
예제 #6
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();
    }
}
예제 #7
0
  /* Invoke all remaining finalizers that haven't yet been run.
   * This is needed for strict compliance with the Java standard,
   * which can make the runtime guarantee that all finalizers are run.
   * Unfortunately, the Java standard implies we have to keep running
   * finalizers until there are no more left, a potential infinite loop.
   * YUCK.
   * Note that this is even more dangerous than the usual Java
   * finalizers, in that objects reachable from static variables
   * may have been finalized when these finalizers are run.
   * Finalizers run at this point must be prepared to deal with a
   * mostly broken world.
   * This routine is externally callable, so is called without
   * the allocation lock.
   */
  GC_API void GC_CALL GC_finalize_all(void)
  {
    DCL_LOCK_STATE;

    LOCK();
    while (GC_fo_entries > 0) {
      GC_enqueue_all_finalizers();
      UNLOCK();
      GC_invoke_finalizers();
      /* Running the finalizers in this thread is arguably not a good   */
      /* idea when we should be notifying another thread to run them.   */
      /* But otherwise we don't have a great way to wait for them to    */
      /* run.                                                           */
      LOCK();
    }
    UNLOCK();
  }
예제 #8
0
/*
 * Tries to invoke finalizers synchronously.
 * Returns 0 if successful or -1 if it would be unsafe to do so.
 */
static int _InvokeFinalizersSynchronously()
{
	unsigned long fg, bg;

	ILThreadGetCounts(&fg, &bg);

	if (!GC_should_invoke_finalizers())
	{
		return 0;
	}
	
	/* Prevent recursive finalization */
	if (_FinalizersRunningSynchronously)
	{
		return 0;
	}

	if (fg + bg > 1)
	{
		/* Threads are supported and there are other threads active so it isn't
		   safe to invoke finalizers synchronously. */

		return -1;
	}
	else
	{
		/* Because there is only one thread active (this thread), it is safe to
		   invoke finalizers synchronously */

		_FinalizersRunning = 1;
		_FinalizersRunningSynchronously = 1;

		GC_invoke_finalizers();

		_FinalizersRunning = 0;
		_FinalizersRunningSynchronously = 0;

		return 0;
	}
}
예제 #9
0
파일: core.c 프로젝트: Z-Shang/Gauche
/* Called from VM loop.  Queue is not empty. */
ScmObj Scm_VMFinalizerRun(ScmVM *vm)
{
    GC_invoke_finalizers();
    vm->finalizerPending = FALSE;
    return SCM_UNDEFINED;
}
예제 #10
0
void finalizer_notify()
{
    GC_invoke_finalizers();
}
예제 #11
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 */
}
예제 #12
0
void test_extras(void)
{
#   define FNAME1 "cordtst1.tmp" /* short name (8+3) for portability */
#   define FNAME2 "cordtst2.tmp"
    register int i;
    CORD y = "abcdefghijklmnopqrstuvwxyz0123456789";
    CORD x = "{}";
    CORD w, z;
    FILE *f;
    FILE *f1a, *f1b, *f2;

    w = CORD_cat(CORD_cat(y,y),y);
    z = CORD_catn(3,y,y,y);
    if (CORD_cmp(w,z) != 0) ABORT("CORD_catn comparison wrong");
    for (i = 1; i < 100; i++) {
        x = CORD_cat(x, y);
    }
    z = CORD_balance(x);
    if (CORD_cmp(x,z) != 0) ABORT("balanced string comparison wrong");
    if (CORD_cmp(x,CORD_cat(z, CORD_nul(13))) >= 0) ABORT("comparison 2");
    if (CORD_cmp(CORD_cat(x, CORD_nul(13)), z) <= 0) ABORT("comparison 3");
    if (CORD_cmp(x,CORD_cat(z, "13")) >= 0) ABORT("comparison 4");
    if ((f = fopen(FNAME1, "w")) == 0) ABORT("open failed");
    if (CORD_put(z,f) == EOF) ABORT("CORD_put failed");
    if (fclose(f) == EOF) ABORT("fclose failed");
    f1a = fopen(FNAME1, "rb");
    if (!f1a) ABORT("Unable to open " FNAME1);
    w = CORD_from_file(f1a);
    if (CORD_len(w) != CORD_len(z)) ABORT("file length wrong");
    if (CORD_cmp(w,z) != 0) ABORT("file comparison wrong");
    if (CORD_cmp(CORD_substr(w, 50*36+2, 36), y) != 0)
        ABORT("file substr wrong");
    f1b = fopen(FNAME1, "rb");
    if (!f1b) ABORT("2nd open failed: " FNAME1);
    z = CORD_from_file_lazy(f1b);
    if (CORD_cmp(w,z) != 0) ABORT("File conversions differ");
    if (CORD_chr(w, 0, '9') != 37) ABORT("CORD_chr failed 1");
    if (CORD_chr(w, 3, 'a') != 38) ABORT("CORD_chr failed 2");
    if (CORD_rchr(w, CORD_len(w) - 1, '}') != 1) ABORT("CORD_rchr failed");
    x = y;
    for (i = 1; i < 14; i++) {
        x = CORD_cat(x,x);
    }
    if ((f = fopen(FNAME2, "w")) == 0) ABORT("2nd open failed");
#   ifdef __DJGPP__
    /* FIXME: DJGPP workaround.  Why does this help? */
    if (fflush(f) != 0) ABORT("fflush failed");
#   endif
    if (CORD_put(x,f) == EOF) ABORT("CORD_put failed");
    if (fclose(f) == EOF) ABORT("fclose failed");
    f2 = fopen(FNAME2, "rb");
    if (!f2) ABORT("Unable to open " FNAME2);
    w = CORD_from_file(f2);
    if (CORD_len(w) != CORD_len(x)) ABORT("file length wrong");
    if (CORD_cmp(w,x) != 0) ABORT("file comparison wrong");
    if (CORD_cmp(CORD_substr(w, 1000*36, 36), y) != 0)
        ABORT("file substr wrong");
    if (strcmp(CORD_to_char_star(CORD_substr(w, 1000*36, 36)), y) != 0)
        ABORT("char * file substr wrong");
    if (strcmp(CORD_substr(w, 1000*36, 2), "ab") != 0)
        ABORT("short file substr wrong");
    if (CORD_str(x,1,"9a") != 35) ABORT("CORD_str failed 1");
    if (CORD_str(x,0,"9abcdefghijk") != 35) ABORT("CORD_str failed 2");
    if (CORD_str(x,0,"9abcdefghijx") != CORD_NOT_FOUND)
        ABORT("CORD_str failed 3");
    if (CORD_str(x,0,"9>") != CORD_NOT_FOUND) ABORT("CORD_str failed 4");
    /* Note: f1a, f1b, f2 handles are closed lazily by CORD library.    */
    /* TODO: Propose and use CORD_fclose. */
    *(CORD volatile *)&w = CORD_EMPTY;
    *(CORD volatile *)&z = CORD_EMPTY;
    GC_gcollect();
    GC_invoke_finalizers();
    /* Of course, this does not guarantee the files are closed. */
    if (remove(FNAME1) != 0) {
        /* On some systems, e.g. OS2, this may fail if f1 is still open. */
        /* But we cannot call fclose as it might lead to double close.   */
        fprintf(stderr, "WARNING: remove(FNAME1) failed\n");
    }
    if (remove(FNAME2) != 0) {
        fprintf(stderr, "WARNING: remove(FNAME2) failed\n");
    }
}