-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004 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
*
* 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
*/
if (ptr)
return ptr;
- scm_rec_mutex_lock (&scm_i_sweep_mutex);
-
+ scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
+ scm_gc_running_p = 1;
+
scm_i_sweep_all_segments ("realloc");
SCM_SYSCALL (ptr = realloc (mem, size));
if (ptr)
{
- scm_rec_mutex_unlock (&scm_i_sweep_mutex);
+ scm_gc_running_p = 0;
+ scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
return ptr;
}
- scm_igc ("realloc");
+ scm_i_gc ("realloc");
scm_i_sweep_all_segments ("realloc");
- scm_rec_mutex_unlock (&scm_i_sweep_mutex);
+ 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));
}
-void
-scm_gc_register_collectable_memory (void *mem, size_t size, const char *what)
+static void
+decrease_mtrigger (size_t size, const char * what)
+{
+ scm_i_pthread_mutex_lock (&scm_i_gc_admin_mutex);
+ 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;
-
- /*
- we could finish the full sweep (without mark) here, but in
- practice this turns out to be ineffective.
- */
+ 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_rec_mutex_lock (&scm_i_sweep_mutex);
+ scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
+ scm_gc_running_p = 1;
- prev_alloced = scm_mallocated;
- scm_igc (what);
+ prev_alloced = mallocated;
+ scm_i_gc (what);
scm_i_sweep_all_segments ("mtrigger");
yield = (((float) prev_alloced - (float) scm_mallocated)
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);
}
-
+}
+
+void
+scm_gc_register_collectable_memory (void *mem, size_t size, const char *what)
+{
+ increase_mtrigger (size, what);
#ifdef GUILE_DEBUG_MALLOC
if (mem)
scm_malloc_register (mem, what);
#endif
}
+
void
scm_gc_unregister_collectable_memory (void *mem, size_t size, const char *what)
{
- scm_mallocated -= size;
- scm_gc_malloc_collected += size;
-
+ decrease_mtrigger (size, what);
#ifdef GUILE_DEBUG_MALLOC
if (mem)
scm_malloc_unregister (mem);
void *
scm_gc_realloc (void *mem, size_t old_size, size_t new_size, const char *what)
{
+ void *ptr;
+
/* XXX - see scm_gc_malloc. */
- void *ptr = scm_realloc (mem, new_size);
- scm_gc_unregister_collectable_memory (mem, old_size, what);
- scm_gc_register_collectable_memory (ptr, new_size, what);
+
+ /*
+ 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().
+ */
+
+ decrease_mtrigger (old_size, what);
+ increase_mtrigger (new_size, what);
+
+ ptr = scm_realloc (mem, new_size);
+
+#ifdef GUILE_DEBUG_MALLOC
+ if (mem)
+ scm_malloc_reregister (mem, ptr, what);
+#endif
+
return ptr;
}
("scm_done_malloc is deprecated. "
"Use scm_gc_register_collectable_memory instead.");
- scm_gc_register_collectable_memory (NULL, size, "foreign mallocs");
+ if (size >= 0)
+ scm_gc_register_collectable_memory (NULL, size, "foreign mallocs");
+ else
+ scm_gc_unregister_collectable_memory (NULL, -size, "foreign mallocs");
}
void
("scm_done_free is deprecated. "
"Use scm_gc_unregister_collectable_memory instead.");
- scm_gc_unregister_collectable_memory (NULL, size, "foreign mallocs");
+ if (size >= 0)
+ scm_gc_unregister_collectable_memory (NULL, size, "foreign mallocs");
+ else
+ scm_gc_register_collectable_memory (NULL, -size, "foreign mallocs");
}
#endif /* SCM_ENABLE_DEPRECATED == 1 */