Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement new toggleref machinery for sgen.

	* sgen-toggleref.c: GC backed toggleref machinery. This enables
	embedders to support toggleref style of external memory management
	without hooking up to the host retain/release machinery.

	The API export two entry points. The first let the caller register
	a callback with sgen that decides the state of a given object, by
	probably inspecting its native state. The second allows registration
	of objects with the toggleref machinery.

	The idea of toggleref is that we keep an external reference to an object
	and it can be  either a strong or weak reference. We use a weak reference
	when the external peer has no interest into the object and a strong otherwise.
  • Loading branch information...
commit f868f65013502de8f01ff014b5a4780f2c07e6df 1 parent 521ab9a
Rodrigo Kumpera kumpera authored
2  mono/metadata/Makefile.am
View
@@ -202,6 +202,8 @@ libmonoruntime_la_SOURCES = \
sgen-protocol.c \
sgen-bridge.c \
sgen-bridge.h \
+ sgen-toggleref.c \
+ sgen-toggleref.h \
sgen-gc.h \
sgen-archdep.h \
sgen-cardtable.h \
7 mono/metadata/sgen-gc.c
View
@@ -2484,6 +2484,10 @@ finish_gray_stack (char *start_addr, char *end_addr, int generation, GrayQueue *
++ephemeron_rounds;
} while (!done_with_ephemerons);
+ mono_sgen_scan_togglerefs (copy_func, start_addr, end_addr, queue);
+ if (generation == GENERATION_OLD)
+ mono_sgen_scan_togglerefs (copy_func, nursery_start, nursery_end, queue);
+
if (mono_sgen_need_bridge_processing ()) {
if (finalized_array == NULL) {
finalized_array_capacity = 32;
@@ -4712,6 +4716,9 @@ stop_world (int generation)
{
int count;
+ /*XXX this is the right stop, thought might not be the nicest place to put it*/
+ mono_sgen_process_togglerefs ();
+
mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
acquire_gc_locks ();
5 mono/metadata/sgen-gc.h
View
@@ -652,6 +652,7 @@ enum {
INTERNAL_MEM_WORKER_DATA,
INTERNAL_MEM_BRIDGE_DATA,
INTERNAL_MEM_JOB_QUEUE_ENTRY,
+ INTERNAL_MEM_TOGGLEREF_DATA,
INTERNAL_MEM_MAX
};
@@ -832,6 +833,10 @@ void mono_sgen_register_test_bridge_callbacks (void) MONO_INTERNAL;
gboolean mono_sgen_is_bridge_object (MonoObject *obj) MONO_INTERNAL;
void mono_sgen_mark_bridge_object (MonoObject *obj) MONO_INTERNAL;
+void mono_sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue) MONO_INTERNAL;
+void mono_sgen_process_togglerefs (void) MONO_INTERNAL;
+
+
gboolean mono_sgen_gc_is_object_ready_for_finalization (void *object) MONO_INTERNAL;
void mono_sgen_gc_lock (void) MONO_INTERNAL;
void mono_sgen_gc_unlock (void) MONO_INTERNAL;
2  mono/metadata/sgen-internal.c
View
@@ -146,7 +146,7 @@ mono_sgen_dump_internal_mem_usage (FILE *heap_dump_file)
"dislink", "roots-table", "root-record", "statistics",
"remset", "gray-queue", "store-remset", "marksweep-tables",
"marksweep-block-info", "ephemeron-link", "worker-data",
- "bridge-data", "job-queue-entry" };
+ "bridge-data", "job-queue-entry", "toggleref-data" };
int i;
198 mono/metadata/sgen-toggleref.c
View
@@ -0,0 +1,198 @@
+/*
+ *
+ * sgen-toggleref.c: toggleref support for sgen
+ *
+ * Copyright 2011 Xamarin, Inc.
+ *
+ * Author:
+ * Rodrigo Kumpera (kumpera@gmail.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "config.h"
+
+#ifdef HAVE_SGEN_GC
+
+#include "sgen-gc.h"
+#include "sgen-toggleref.h"
+
+
+/*only one of the two can be non null at a given time*/
+typedef struct {
+ void *strong_ref;
+ void *weak_ref;
+} MonoGCToggleRef;
+
+static MonoToggleRefStatus (*toggleref_callback) (MonoObject *obj);
+static MonoGCToggleRef *toggleref_array;
+static int toogleref_array_size;
+static int toogleref_array_capacity;
+
+void
+mono_sgen_process_togglerefs (void)
+{
+ int i, w;
+ int toggle_ref_counts [3] = { 0 };
+
+ DEBUG (4, fprintf (gc_debug_file, "Proccessing ToggleRefs %d\n", toogleref_array_size));
+
+ for (i = w = 0; i < toogleref_array_size; ++i) {
+ int res;
+ MonoGCToggleRef r = toggleref_array [i];
+
+ MonoObject *obj;
+
+ if (r.strong_ref)
+ obj = r.strong_ref;
+ else if (r.weak_ref)
+ obj = r.weak_ref;
+ else
+ continue;
+
+ res = toggleref_callback (obj);
+ ++toggle_ref_counts [res];
+ switch (res) {
+ case MONO_TOGGLE_REF_DROP:
+ break;
+ case MONO_TOGGLE_REF_STRONG:
+ toggleref_array [w].strong_ref = obj;
+ toggleref_array [w].weak_ref = NULL;
+ ++w;
+ break;
+ case MONO_TOGGLE_REF_WEAK:
+ toggleref_array [w].strong_ref = NULL;
+ toggleref_array [w].weak_ref = obj;
+ ++w;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ toogleref_array_size = w;
+
+ DEBUG (4, fprintf (gc_debug_file, "Done Proccessing ToggleRefs dropped %d strong %d weak %d final size %d\n",
+ toggle_ref_counts [MONO_TOGGLE_REF_DROP],
+ toggle_ref_counts [MONO_TOGGLE_REF_STRONG],
+ toggle_ref_counts [MONO_TOGGLE_REF_WEAK],
+ w));
+}
+
+void
+mono_sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue)
+{
+ int i;
+
+ DEBUG (4, fprintf (gc_debug_file, "Scanning ToggleRefs %d\n", toogleref_array_size));
+
+ for (i = 0; i < toogleref_array_size; ++i) {
+ if (toggleref_array [i].strong_ref) {
+ char *object = toggleref_array [i].strong_ref;
+ if (object >= start && object < end) {
+ DEBUG (6, fprintf (gc_debug_file, "\tcopying strong slot %d\n", i));
+ copy_func (&toggleref_array [i].strong_ref, queue);
+ }
+ } else if (toggleref_array [i].weak_ref) {
+ char *object = toggleref_array [i].weak_ref;
+
+ if (object >= start && object < end) {
+ if (mono_sgen_gc_is_object_ready_for_finalization (object)) {
+ DEBUG (6, fprintf (gc_debug_file, "\tcleaning weak slot %d\n", i));
+ toggleref_array [i].weak_ref = NULL; /* We defer compaction to only happen on the callback step. */
+ } else {
+ DEBUG (6, fprintf (gc_debug_file, "\tkeeping weak slot %d\n", i));
+ copy_func (&toggleref_array [i].weak_ref, queue);
+ }
+ }
+ }
+ }
+}
+
+static void
+ensure_toggleref_capacity (int capacity)
+{
+ if (!toggleref_array) {
+ toogleref_array_capacity = 32;
+ toggleref_array = mono_sgen_alloc_internal_dynamic (
+ toogleref_array_capacity * sizeof (MonoGCToggleRef),
+ INTERNAL_MEM_TOGGLEREF_DATA);
+ }
+ if (toogleref_array_size + capacity >= toogleref_array_capacity) {
+ MonoGCToggleRef *tmp;
+ int old_capacity = toogleref_array_capacity;
+ while (toogleref_array_capacity < toogleref_array_size + capacity)
+ toogleref_array_size *= 2;
+
+ tmp = mono_sgen_alloc_internal_dynamic (
+ toogleref_array_capacity * sizeof (MonoGCToggleRef),
+ INTERNAL_MEM_TOGGLEREF_DATA);
+
+ memcpy (tmp, toggleref_array, toogleref_array_size * sizeof (MonoGCToggleRef));
+
+ mono_sgen_free_internal_dynamic (toggleref_array, old_capacity * sizeof (MonoGCToggleRef), INTERNAL_MEM_TOGGLEREF_DATA);
+ toggleref_array = tmp;
+ }
+}
+
+/**
+ * mono_gc_toggleref_add:
+ * @object object to register for toggleref processing
+ * @strong_ref if true the object is registered with a strong ref, a weak one otherwise
+ *
+ * Register a given object for toggleref processing. It will be stored internally and the toggleref callback will be called
+ * on it until it returns MONO_TOGGLE_REF_DROP or is collected.
+*/
+void
+mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
+{
+ if (!toggleref_callback)
+ return;
+
+ DEBUG (4, fprintf (gc_debug_file, "Adding toggleref %p %d\n", object, strong_ref));
+
+ mono_sgen_gc_lock ();
+
+ ensure_toggleref_capacity (1);
+ if (strong_ref)
+ toggleref_array [toogleref_array_size++].strong_ref = object;
+ else
+ toggleref_array [toogleref_array_size++].weak_ref = object;
+
+ mono_sgen_gc_unlock;
+}
+
+/**
+ * mono_gc_toggleref_register_callback:
+ * @callback callback used to determine the new state of the given object.
+ *
+ * The callback must decide the status of a given object. It must return one of the values in the MONO_TOGGLE_REF_ enum.
+ * This function is called with the world running but with the GC locked. This means that you can do everything that doesn't
+ * require GC interaction. This includes, but not limited to, allocating objects, (de)registering for finalization, manipulating
+ *gchandles, storing to reference fields or interacting with other threads that might perform such operations.
+ */
+void
+mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
+{
+ toggleref_callback = proccess_toggleref;
+}
+
+#endif
51 mono/metadata/sgen-toggleref.h
View
@@ -0,0 +1,51 @@
+/*
+ *
+ * sgen-toggleref.h: toggleref support for sgen
+ *
+ * Copyright 2011 Xamarin, Inc.
+ *
+ * Author:
+ * Rodrigo Kumpera (kumpera@gmail.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _MONO_SGEN_TOGGLEREF_H_
+#define _MONO_SGEN_TOGGLEREF_H_
+
+#include <mono/utils/mono-publib.h>
+
+MONO_BEGIN_DECLS
+
+/* GC toggle ref support */
+
+typedef enum {
+ MONO_TOGGLE_REF_DROP,
+ MONO_TOGGLE_REF_STRONG,
+ MONO_TOGGLE_REF_WEAK
+} MonoToggleRefStatus;
+
+void mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj));
+void mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref);
+
+
+MONO_END_DECLS
+
+#endif
Please sign in to comment.
Something went wrong with that request. Please try again.