summaryrefslogtreecommitdiff
path: root/stubborn.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2011-07-26 18:09:54 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 18:09:54 +0200
commite35a4171fe47dfbf847e08988ea6cec4dfc8d124 (patch)
tree25f3501669fbf24a4b370c4f8b0c0701b1da4062 /stubborn.c
parentffa0c9ea38b3dd87e91b5ed2118c74002fed6782 (diff)
gc7.0alpha1 tarball importgc7_0alpha1
Diffstat (limited to 'stubborn.c')
-rw-r--r--stubborn.c302
1 files changed, 17 insertions, 285 deletions
diff --git a/stubborn.c b/stubborn.c
index bb13761..f4e0958 100644
--- a/stubborn.c
+++ b/stubborn.c
@@ -16,311 +16,43 @@
#include "private/gc_priv.h"
-# ifdef STUBBORN_ALLOC
+#if defined(MANUAL_VDB)
/* Stubborn object (hard to change, nearly immutable) allocation. */
-
-extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
-
-#define GENERAL_MALLOC(lb,k) \
- (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
-
-/* Data structure representing immutable objects that */
-/* are still being initialized. */
-/* This is a bit baroque in order to avoid acquiring */
-/* the lock twice for a typical allocation. */
-
-GC_PTR * GC_changing_list_start;
-
-void GC_push_stubborn_structures GC_PROTO((void))
-{
- GC_push_all((ptr_t)(&GC_changing_list_start),
- (ptr_t)(&GC_changing_list_start) + sizeof(GC_PTR *));
-}
-
-# ifdef THREADS
- VOLATILE GC_PTR * VOLATILE GC_changing_list_current;
-# else
- GC_PTR * GC_changing_list_current;
-# endif
- /* Points at last added element. Also (ab)used for */
- /* synchronization. Updates and reads are assumed atomic. */
-
-GC_PTR * GC_changing_list_limit;
- /* Points at the last word of the buffer, which is always 0 */
- /* All entries in (GC_changing_list_current, */
- /* GC_changing_list_limit] are 0 */
-
-
-void GC_stubborn_init()
-{
-# define INIT_SIZE 10
-
- GC_changing_list_start = (GC_PTR *)
- GC_INTERNAL_MALLOC(
- (word)(INIT_SIZE * sizeof(GC_PTR)),
- PTRFREE);
- BZERO(GC_changing_list_start,
- INIT_SIZE * sizeof(GC_PTR));
- if (GC_changing_list_start == 0) {
- GC_err_printf0("Insufficient space to start up\n");
- ABORT("GC_stubborn_init: put of space");
- }
- GC_changing_list_current = GC_changing_list_start;
- GC_changing_list_limit = GC_changing_list_start + INIT_SIZE - 1;
- * GC_changing_list_limit = 0;
-}
-
-/* Compact and possibly grow GC_uninit_list. The old copy is */
-/* left alone. Lock must be held. */
-/* When called GC_changing_list_current == GC_changing_list_limit */
-/* which is one past the current element. */
-/* When we finish GC_changing_list_current again points one past last */
-/* element. */
-/* Invariant while this is running: GC_changing_list_current */
-/* points at a word containing 0. */
-/* Returns FALSE on failure. */
-GC_bool GC_compact_changing_list()
-{
- register GC_PTR *p, *q;
- register word count = 0;
- word old_size = (char **)GC_changing_list_limit
- - (char **)GC_changing_list_start+1;
- /* The casts are needed as a workaround for an Amiga bug */
- register word new_size = old_size;
- GC_PTR * new_list;
-
- for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
- if (*p != 0) count++;
- }
- if (2 * count > old_size) new_size = 2 * count;
- new_list = (GC_PTR *)
- GC_INTERNAL_MALLOC(
- new_size * sizeof(GC_PTR), PTRFREE);
- /* PTRFREE is a lie. But we don't want the collector to */
- /* consider these. We do want the list itself to be */
- /* collectable. */
- if (new_list == 0) return(FALSE);
- BZERO(new_list, new_size * sizeof(GC_PTR));
- q = new_list;
- for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
- if (*p != 0) *q++ = *p;
- }
- GC_changing_list_start = new_list;
- GC_changing_list_limit = new_list + new_size - 1;
- GC_changing_list_current = q;
- return(TRUE);
-}
-
-/* Add p to changing list. Clear p on failure. */
-# define ADD_CHANGING(p) \
- { \
- register struct hblk * h = HBLKPTR(p); \
- register word index = PHT_HASH(h); \
- \
- set_pht_entry_from_index(GC_changed_pages, index); \
- } \
- if (*GC_changing_list_current != 0 \
- && ++GC_changing_list_current == GC_changing_list_limit) { \
- if (!GC_compact_changing_list()) (p) = 0; \
- } \
- *GC_changing_list_current = p;
-
-void GC_change_stubborn(p)
-GC_PTR p;
-{
- DCL_LOCK_STATE;
-
- DISABLE_SIGNALS();
- LOCK();
- ADD_CHANGING(p);
- UNLOCK();
- ENABLE_SIGNALS();
-}
-
-void GC_end_stubborn_change(p)
-GC_PTR p;
-{
-# ifdef THREADS
- register VOLATILE GC_PTR * my_current = GC_changing_list_current;
-# else
- register GC_PTR * my_current = GC_changing_list_current;
-# endif
- register GC_bool tried_quick;
- DCL_LOCK_STATE;
-
- if (*my_current == p) {
- /* Hopefully the normal case. */
- /* Compaction could not have been running when we started. */
- *my_current = 0;
-# ifdef THREADS
- if (my_current == GC_changing_list_current) {
- /* Compaction can't have run in the interim. */
- /* We got away with the quick and dirty approach. */
- return;
- }
- tried_quick = TRUE;
-# else
- return;
-# endif
- } else {
- tried_quick = FALSE;
- }
- DISABLE_SIGNALS();
- LOCK();
- my_current = GC_changing_list_current;
- for (; my_current >= GC_changing_list_start; my_current--) {
- if (*my_current == p) {
- *my_current = 0;
- UNLOCK();
- ENABLE_SIGNALS();
- return;
- }
- }
- if (!tried_quick) {
- GC_err_printf1("Bad arg to GC_end_stubborn_change: 0x%lx\n",
- (unsigned long)p);
- ABORT("Bad arg to GC_end_stubborn_change");
- }
- UNLOCK();
- ENABLE_SIGNALS();
-}
-
-/* Allocate lb bytes of composite (pointerful) data */
-/* No pointer fields may be changed after a call to */
-/* GC_end_stubborn_change(p) where p is the value */
-/* returned by GC_malloc_stubborn. */
-# ifdef __STDC__
- GC_PTR GC_malloc_stubborn(size_t lb)
-# else
- GC_PTR GC_malloc_stubborn(lb)
- size_t lb;
-# endif
-{
-register ptr_t op;
-register ptr_t *opp;
-register word lw;
-ptr_t result;
-DCL_LOCK_STATE;
-
- if( SMALL_OBJ(lb) ) {
-# ifdef MERGE_SIZES
- lw = GC_size_map[lb];
-# else
- lw = ALIGNED_WORDS(lb);
-# endif
- opp = &(GC_sobjfreelist[lw]);
- FASTLOCK();
- if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
- FASTUNLOCK();
- result = GC_generic_malloc((word)lb, STUBBORN);
- goto record;
- }
- *opp = obj_link(op);
- obj_link(op) = 0;
- GC_words_allocd += lw;
- result = (GC_PTR) op;
- ADD_CHANGING(result);
- FASTUNLOCK();
- return((GC_PTR)result);
- } else {
- result = (GC_PTR)
- GC_generic_malloc((word)lb, STUBBORN);
- }
-record:
- DISABLE_SIGNALS();
- LOCK();
- ADD_CHANGING(result);
- UNLOCK();
- ENABLE_SIGNALS();
- return((GC_PTR)GC_clear_stack(result));
-}
-
-
-/* Functions analogous to GC_read_dirty and GC_page_was_dirty. */
-/* Report pages on which stubborn objects were changed. */
-void GC_read_changed()
+/* This interface is deprecated. We mostly emulate it using */
+/* MANUAL_VDB. But that imposes the additional constraint that */
+/* written, but not yet GC_dirty()ed objects must be referenced */
+/* by a stack. */
+void * GC_malloc_stubborn(size_t lb)
{
- register GC_PTR * p = GC_changing_list_start;
- register GC_PTR q;
- register struct hblk * h;
- register word index;
-
- if (p == 0) /* initializing */ return;
- BCOPY(GC_changed_pages, GC_prev_changed_pages,
- (sizeof GC_changed_pages));
- BZERO(GC_changed_pages, (sizeof GC_changed_pages));
- for (; p <= GC_changing_list_current; p++) {
- if ((q = *p) != 0) {
- h = HBLKPTR(q);
- index = PHT_HASH(h);
- set_pht_entry_from_index(GC_changed_pages, index);
- }
- }
+ return(GC_malloc(lb));
}
-GC_bool GC_page_was_changed(h)
-struct hblk * h;
+/*ARGSUSED*/
+void GC_end_stubborn_change(void *p)
{
- register word index = PHT_HASH(h);
-
- return(get_pht_entry_from_index(GC_prev_changed_pages, index));
+ GC_dirty(p);
}
-/* Remove unreachable entries from changed list. Should only be */
-/* called with mark bits consistent and lock held. */
-void GC_clean_changing_list()
+/*ARGSUSED*/
+void GC_change_stubborn(void *p)
{
- register GC_PTR * p = GC_changing_list_start;
- register GC_PTR q;
- register ptr_t r;
- register unsigned long count = 0;
- register unsigned long dropped_count = 0;
-
- if (p == 0) /* initializing */ return;
- for (; p <= GC_changing_list_current; p++) {
- if ((q = *p) != 0) {
- count++;
- r = (ptr_t)GC_base(q);
- if (r == 0 || !GC_is_marked(r)) {
- *p = 0;
- dropped_count++;
- }
- }
- }
-# ifdef PRINTSTATS
- if (count > 0) {
- GC_printf2("%lu entries in changing list: reclaimed %lu\n",
- (unsigned long)count, (unsigned long)dropped_count);
- }
-# endif
}
-#else /* !STUBBORN_ALLOC */
+#else /* !MANUAL_VDB */
-# ifdef __STDC__
- GC_PTR GC_malloc_stubborn(size_t lb)
-# else
- GC_PTR GC_malloc_stubborn(lb)
- size_t lb;
-# endif
+void * GC_malloc_stubborn(size_t lb)
{
return(GC_malloc(lb));
}
/*ARGSUSED*/
-void GC_end_stubborn_change(p)
-GC_PTR p;
+void GC_end_stubborn_change(void *p)
{
}
/*ARGSUSED*/
-void GC_change_stubborn(p)
-GC_PTR p;
-{
-}
-
-void GC_push_stubborn_structures GC_PROTO((void))
+void GC_change_stubborn(void *p)
{
}
-#endif
+#endif /* !MANUAL_VDB */