-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*/
\f
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
void
scm_gc_init_malloc (void)
{
- scm_mtrigger = scm_getenv_int ("GUILE_INIT_MALLOC_LIMIT",
+ int mtrigger = scm_getenv_int ("GUILE_INIT_MALLOC_LIMIT",
SCM_DEFAULT_INIT_MALLOC_LIMIT);
- scm_i_minyield_malloc = scm_getenv_int ("GUILE_MIN_YIELD_MALLOC",
- SCM_DEFAULT_MALLOC_MINYIELD);
+ scm_i_minyield_malloc = scm_getenv_int ("GUILE_MIN_YIELD_MALLOC",
+ SCM_DEFAULT_MALLOC_MINYIELD);
if (scm_i_minyield_malloc >= 100)
scm_i_minyield_malloc = 99;
if (scm_i_minyield_malloc < 1)
scm_i_minyield_malloc = 1;
- if (scm_mtrigger < 0)
+ if (mtrigger < 0)
scm_mtrigger = SCM_DEFAULT_INIT_MALLOC_LIMIT;
+ else
+ scm_mtrigger = mtrigger;
}
if (ptr)
return ptr;
- scm_rec_mutex_lock (&scm_i_sweep_mutex);
-
- scm_i_sweep_all_segments ("realloc");
-
- SCM_SYSCALL (ptr = realloc (mem, size));
- if (ptr)
- {
- scm_rec_mutex_unlock (&scm_i_sweep_mutex);
- return ptr;
- }
+ scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
+ scm_gc_running_p = 1;
- scm_igc ("realloc");
- scm_i_sweep_all_segments ("realloc");
-
- scm_rec_mutex_unlock (&scm_i_sweep_mutex);
+ scm_i_gc ("realloc");
+
+ /*
+ We don't want these sweep statistics to influence results for
+ cell GC, so we don't collect statistics.
+
+ realloc () failed, so we're really desparate to free memory. Run a
+ full sweep.
+ */
+ scm_i_sweep_all_segments ("realloc", NULL);
+
+ scm_gc_running_p = 0;
+ scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr)
return scm_strndup (str, strlen (str));
}
-
static void
decrease_mtrigger (size_t size, const char * what)
{
+ scm_i_pthread_mutex_lock (&scm_i_gc_admin_mutex);
+
+ if (size > scm_mallocated)
+ {
+ fprintf (stderr, "`scm_mallocated' underflow. This means that more "
+ "memory was unregistered\n"
+ "via `scm_gc_unregister_collectable_memory ()' than "
+ "registered.\n");
+ abort ();
+ }
+
scm_mallocated -= size;
scm_gc_malloc_collected += size;
+ scm_i_pthread_mutex_unlock (&scm_i_gc_admin_mutex);
}
static void
increase_mtrigger (size_t size, const char *what)
{
+ size_t mallocated = 0;
+ int overflow = 0, triggered = 0;
+
+ scm_i_pthread_mutex_lock (&scm_i_gc_admin_mutex);
if (ULONG_MAX - size < scm_mallocated)
+ overflow = 1;
+ else
{
- scm_memory_error ("Overflow of scm_mallocated: too much memory in use.");
+ scm_mallocated += size;
+ mallocated = scm_mallocated;
+ if (scm_mallocated > scm_mtrigger)
+ triggered = 1;
}
+ scm_i_pthread_mutex_unlock (&scm_i_gc_admin_mutex);
- scm_mallocated += size;
+ if (overflow)
+ scm_memory_error ("Overflow of scm_mallocated: too much memory in use.");
/*
A program that uses a lot of malloced collectable memory (vectors,
do GC more often (before cells are exhausted), otherwise swapping
and malloc management will tie it down.
*/
- if (scm_mallocated > scm_mtrigger)
+ if (triggered)
{
unsigned long prev_alloced;
float yield;
+
+ scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
+ scm_gc_running_p = 1;
- scm_rec_mutex_lock (&scm_i_sweep_mutex);
-
- prev_alloced = scm_mallocated;
- scm_igc (what);
- scm_i_sweep_all_segments ("mtrigger");
+ prev_alloced = mallocated;
+
+ /* The GC will finish the pending sweep. For that reason, we
+ don't execute a complete sweep after GC, although that might
+ free some more memory.
+ */
+ scm_i_gc (what);
yield = (((float) prev_alloced - (float) scm_mallocated)
/ (float) prev_alloced);
- scm_gc_malloc_yield_percentage = (int) (100 * yield);
+ scm_gc_malloc_yield_percentage = (int) (100 * yield);
#ifdef DEBUGINFO
fprintf (stderr, "prev %lud , now %lud, yield %4.2lf, want %d",
if (no_overflow_trigger >= (float) ULONG_MAX)
scm_mtrigger = ULONG_MAX;
else
- scm_mtrigger = (unsigned long) no_overflow_trigger;
+ scm_mtrigger = (unsigned long) no_overflow_trigger;
#ifdef DEBUGINFO
fprintf (stderr, "Mtrigger sweep: ineffective. New trigger %d\n",
scm_mtrigger);
#endif
}
-
- scm_rec_mutex_unlock (&scm_i_sweep_mutex);
+
+ scm_gc_running_p = 0;
+ scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
}
}
again in scm_gc_register_collectable_memory. We don't really
want the second GC since it will not find new garbage.
- Note: this is a theoretical peeve. In reality, malloc() never
+ Note: this is a theoretical peeve. In reality, malloc () never
returns NULL. Usually, memory is overcommitted, and when you try
to write it the program is killed with signal 11. --hwn
*/
- void *ptr = scm_malloc (size);
+ void *ptr = size ? scm_malloc (size) : NULL;
scm_gc_register_collectable_memory (ptr, size, what);
return ptr;
}
/*
- scm_realloc() may invalidate the block pointed to by WHERE, eg. by
+ scm_realloc () may invalidate the block pointed to by WHERE, eg. by
unmapping it from memory or altering the contents. Since
- increase_mtrigger() might trigger a GC that would scan
- MEM, it is crucial that this call precedes realloc().
+ increase_mtrigger () might trigger a GC that would scan
+ MEM, it is crucial that this call precedes realloc ().
*/
decrease_mtrigger (old_size, what);
scm_gc_free (void *mem, size_t size, const char *what)
{
scm_gc_unregister_collectable_memory (mem, size, what);
- free (mem);
+ if (mem)
+ free (mem);
}
char *