Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
@@ -202,6 +202,8 @@ libmonoruntime_la_SOURCES = \
202 202 sgen-protocol.c \
203 203 sgen-bridge.c \
204 204 sgen-bridge.h \
  205 + sgen-toggleref.c \
  206 + sgen-toggleref.h \
205 207 sgen-gc.h \
206 208 sgen-archdep.h \
207 209 sgen-cardtable.h \
7 mono/metadata/sgen-gc.c
@@ -2484,6 +2484,10 @@ finish_gray_stack (char *start_addr, char *end_addr, int generation, GrayQueue *
2484 2484 ++ephemeron_rounds;
2485 2485 } while (!done_with_ephemerons);
2486 2486
  2487 + mono_sgen_scan_togglerefs (copy_func, start_addr, end_addr, queue);
  2488 + if (generation == GENERATION_OLD)
  2489 + mono_sgen_scan_togglerefs (copy_func, nursery_start, nursery_end, queue);
  2490 +
2487 2491 if (mono_sgen_need_bridge_processing ()) {
2488 2492 if (finalized_array == NULL) {
2489 2493 finalized_array_capacity = 32;
@@ -4712,6 +4716,9 @@ stop_world (int generation)
4712 4716 {
4713 4717 int count;
4714 4718
  4719 + /*XXX this is the right stop, thought might not be the nicest place to put it*/
  4720 + mono_sgen_process_togglerefs ();
  4721 +
4715 4722 mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD, generation);
4716 4723 acquire_gc_locks ();
4717 4724
5 mono/metadata/sgen-gc.h
@@ -652,6 +652,7 @@ enum {
652 652 INTERNAL_MEM_WORKER_DATA,
653 653 INTERNAL_MEM_BRIDGE_DATA,
654 654 INTERNAL_MEM_JOB_QUEUE_ENTRY,
  655 + INTERNAL_MEM_TOGGLEREF_DATA,
655 656 INTERNAL_MEM_MAX
656 657 };
657 658
@@ -832,6 +833,10 @@ void mono_sgen_register_test_bridge_callbacks (void) MONO_INTERNAL;
832 833 gboolean mono_sgen_is_bridge_object (MonoObject *obj) MONO_INTERNAL;
833 834 void mono_sgen_mark_bridge_object (MonoObject *obj) MONO_INTERNAL;
834 835
  836 +void mono_sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue) MONO_INTERNAL;
  837 +void mono_sgen_process_togglerefs (void) MONO_INTERNAL;
  838 +
  839 +
835 840 gboolean mono_sgen_gc_is_object_ready_for_finalization (void *object) MONO_INTERNAL;
836 841 void mono_sgen_gc_lock (void) MONO_INTERNAL;
837 842 void mono_sgen_gc_unlock (void) MONO_INTERNAL;
2  mono/metadata/sgen-internal.c
@@ -146,7 +146,7 @@ mono_sgen_dump_internal_mem_usage (FILE *heap_dump_file)
146 146 "dislink", "roots-table", "root-record", "statistics",
147 147 "remset", "gray-queue", "store-remset", "marksweep-tables",
148 148 "marksweep-block-info", "ephemeron-link", "worker-data",
149   - "bridge-data", "job-queue-entry" };
  149 + "bridge-data", "job-queue-entry", "toggleref-data" };
150 150
151 151 int i;
152 152
198 mono/metadata/sgen-toggleref.c
... ... @@ -0,0 +1,198 @@
  1 +/*
  2 + *
  3 + * sgen-toggleref.c: toggleref support for sgen
  4 + *
  5 + * Copyright 2011 Xamarin, Inc.
  6 + *
  7 + * Author:
  8 + * Rodrigo Kumpera (kumpera@gmail.com)
  9 + *
  10 + * Permission is hereby granted, free of charge, to any person obtaining
  11 + * a copy of this software and associated documentation files (the
  12 + * "Software"), to deal in the Software without restriction, including
  13 + * without limitation the rights to use, copy, modify, merge, publish,
  14 + * distribute, sublicense, and/or sell copies of the Software, and to
  15 + * permit persons to whom the Software is furnished to do so, subject to
  16 + * the following conditions:
  17 + *
  18 + * The above copyright notice and this permission notice shall be
  19 + * included in all copies or substantial portions of the Software.
  20 + *
  21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25 + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26 + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28 + */
  29 +
  30 +
  31 +#include "config.h"
  32 +
  33 +#ifdef HAVE_SGEN_GC
  34 +
  35 +#include "sgen-gc.h"
  36 +#include "sgen-toggleref.h"
  37 +
  38 +
  39 +/*only one of the two can be non null at a given time*/
  40 +typedef struct {
  41 + void *strong_ref;
  42 + void *weak_ref;
  43 +} MonoGCToggleRef;
  44 +
  45 +static MonoToggleRefStatus (*toggleref_callback) (MonoObject *obj);
  46 +static MonoGCToggleRef *toggleref_array;
  47 +static int toogleref_array_size;
  48 +static int toogleref_array_capacity;
  49 +
  50 +void
  51 +mono_sgen_process_togglerefs (void)
  52 +{
  53 + int i, w;
  54 + int toggle_ref_counts [3] = { 0 };
  55 +
  56 + DEBUG (4, fprintf (gc_debug_file, "Proccessing ToggleRefs %d\n", toogleref_array_size));
  57 +
  58 + for (i = w = 0; i < toogleref_array_size; ++i) {
  59 + int res;
  60 + MonoGCToggleRef r = toggleref_array [i];
  61 +
  62 + MonoObject *obj;
  63 +
  64 + if (r.strong_ref)
  65 + obj = r.strong_ref;
  66 + else if (r.weak_ref)
  67 + obj = r.weak_ref;
  68 + else
  69 + continue;
  70 +
  71 + res = toggleref_callback (obj);
  72 + ++toggle_ref_counts [res];
  73 + switch (res) {
  74 + case MONO_TOGGLE_REF_DROP:
  75 + break;
  76 + case MONO_TOGGLE_REF_STRONG:
  77 + toggleref_array [w].strong_ref = obj;
  78 + toggleref_array [w].weak_ref = NULL;
  79 + ++w;
  80 + break;
  81 + case MONO_TOGGLE_REF_WEAK:
  82 + toggleref_array [w].strong_ref = NULL;
  83 + toggleref_array [w].weak_ref = obj;
  84 + ++w;
  85 + break;
  86 + default:
  87 + g_assert_not_reached ();
  88 + }
  89 + }
  90 +
  91 + toogleref_array_size = w;
  92 +
  93 + DEBUG (4, fprintf (gc_debug_file, "Done Proccessing ToggleRefs dropped %d strong %d weak %d final size %d\n",
  94 + toggle_ref_counts [MONO_TOGGLE_REF_DROP],
  95 + toggle_ref_counts [MONO_TOGGLE_REF_STRONG],
  96 + toggle_ref_counts [MONO_TOGGLE_REF_WEAK],
  97 + w));
  98 +}
  99 +
  100 +void
  101 +mono_sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue)
  102 +{
  103 + int i;
  104 +
  105 + DEBUG (4, fprintf (gc_debug_file, "Scanning ToggleRefs %d\n", toogleref_array_size));
  106 +
  107 + for (i = 0; i < toogleref_array_size; ++i) {
  108 + if (toggleref_array [i].strong_ref) {
  109 + char *object = toggleref_array [i].strong_ref;
  110 + if (object >= start && object < end) {
  111 + DEBUG (6, fprintf (gc_debug_file, "\tcopying strong slot %d\n", i));
  112 + copy_func (&toggleref_array [i].strong_ref, queue);
  113 + }
  114 + } else if (toggleref_array [i].weak_ref) {
  115 + char *object = toggleref_array [i].weak_ref;
  116 +
  117 + if (object >= start && object < end) {
  118 + if (mono_sgen_gc_is_object_ready_for_finalization (object)) {
  119 + DEBUG (6, fprintf (gc_debug_file, "\tcleaning weak slot %d\n", i));
  120 + toggleref_array [i].weak_ref = NULL; /* We defer compaction to only happen on the callback step. */
  121 + } else {
  122 + DEBUG (6, fprintf (gc_debug_file, "\tkeeping weak slot %d\n", i));
  123 + copy_func (&toggleref_array [i].weak_ref, queue);
  124 + }
  125 + }
  126 + }
  127 + }
  128 +}
  129 +
  130 +static void
  131 +ensure_toggleref_capacity (int capacity)
  132 +{
  133 + if (!toggleref_array) {
  134 + toogleref_array_capacity = 32;
  135 + toggleref_array = mono_sgen_alloc_internal_dynamic (
  136 + toogleref_array_capacity * sizeof (MonoGCToggleRef),
  137 + INTERNAL_MEM_TOGGLEREF_DATA);
  138 + }
  139 + if (toogleref_array_size + capacity >= toogleref_array_capacity) {
  140 + MonoGCToggleRef *tmp;
  141 + int old_capacity = toogleref_array_capacity;
  142 + while (toogleref_array_capacity < toogleref_array_size + capacity)
  143 + toogleref_array_size *= 2;
  144 +
  145 + tmp = mono_sgen_alloc_internal_dynamic (
  146 + toogleref_array_capacity * sizeof (MonoGCToggleRef),
  147 + INTERNAL_MEM_TOGGLEREF_DATA);
  148 +
  149 + memcpy (tmp, toggleref_array, toogleref_array_size * sizeof (MonoGCToggleRef));
  150 +
  151 + mono_sgen_free_internal_dynamic (toggleref_array, old_capacity * sizeof (MonoGCToggleRef), INTERNAL_MEM_TOGGLEREF_DATA);
  152 + toggleref_array = tmp;
  153 + }
  154 +}
  155 +
  156 +/**
  157 + * mono_gc_toggleref_add:
  158 + * @object object to register for toggleref processing
  159 + * @strong_ref if true the object is registered with a strong ref, a weak one otherwise
  160 + *
  161 + * Register a given object for toggleref processing. It will be stored internally and the toggleref callback will be called
  162 + * on it until it returns MONO_TOGGLE_REF_DROP or is collected.
  163 +*/
  164 +void
  165 +mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
  166 +{
  167 + if (!toggleref_callback)
  168 + return;
  169 +
  170 + DEBUG (4, fprintf (gc_debug_file, "Adding toggleref %p %d\n", object, strong_ref));
  171 +
  172 + mono_sgen_gc_lock ();
  173 +
  174 + ensure_toggleref_capacity (1);
  175 + if (strong_ref)
  176 + toggleref_array [toogleref_array_size++].strong_ref = object;
  177 + else
  178 + toggleref_array [toogleref_array_size++].weak_ref = object;
  179 +
  180 + mono_sgen_gc_unlock;
  181 +}
  182 +
  183 +/**
  184 + * mono_gc_toggleref_register_callback:
  185 + * @callback callback used to determine the new state of the given object.
  186 + *
  187 + * The callback must decide the status of a given object. It must return one of the values in the MONO_TOGGLE_REF_ enum.
  188 + * This function is called with the world running but with the GC locked. This means that you can do everything that doesn't
  189 + * require GC interaction. This includes, but not limited to, allocating objects, (de)registering for finalization, manipulating
  190 + *gchandles, storing to reference fields or interacting with other threads that might perform such operations.
  191 + */
  192 +void
  193 +mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
  194 +{
  195 + toggleref_callback = proccess_toggleref;
  196 +}
  197 +
  198 +#endif
51 mono/metadata/sgen-toggleref.h
... ... @@ -0,0 +1,51 @@
  1 +/*
  2 + *
  3 + * sgen-toggleref.h: toggleref support for sgen
  4 + *
  5 + * Copyright 2011 Xamarin, Inc.
  6 + *
  7 + * Author:
  8 + * Rodrigo Kumpera (kumpera@gmail.com)
  9 + *
  10 + * Permission is hereby granted, free of charge, to any person obtaining
  11 + * a copy of this software and associated documentation files (the
  12 + * "Software"), to deal in the Software without restriction, including
  13 + * without limitation the rights to use, copy, modify, merge, publish,
  14 + * distribute, sublicense, and/or sell copies of the Software, and to
  15 + * permit persons to whom the Software is furnished to do so, subject to
  16 + * the following conditions:
  17 + *
  18 + * The above copyright notice and this permission notice shall be
  19 + * included in all copies or substantial portions of the Software.
  20 + *
  21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25 + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26 + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28 + */
  29 +
  30 +#ifndef _MONO_SGEN_TOGGLEREF_H_
  31 +#define _MONO_SGEN_TOGGLEREF_H_
  32 +
  33 +#include <mono/utils/mono-publib.h>
  34 +
  35 +MONO_BEGIN_DECLS
  36 +
  37 +/* GC toggle ref support */
  38 +
  39 +typedef enum {
  40 + MONO_TOGGLE_REF_DROP,
  41 + MONO_TOGGLE_REF_STRONG,
  42 + MONO_TOGGLE_REF_WEAK
  43 +} MonoToggleRefStatus;
  44 +
  45 +void mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj));
  46 +void mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref);
  47 +
  48 +
  49 +MONO_END_DECLS
  50 +
  51 +#endif

0 comments on commit f868f65

Please sign in to comment.
Something went wrong with that request. Please try again.