-/*
- * sgen-pinning.c: The pin queue.
+/**
+ * \file
+ * The pin queue.
*
* Copyright 2001-2003 Ximian, Inc
* Copyright 2003-2010 Novell, Inc.
* Copyright (C) 2012 Xamarin Inc
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License 2.0 as published by the Free Software Foundation;
- *
- * 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License 2.0 along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "config.h"
static SgenPointerQueue pin_queue;
static size_t last_num_pinned = 0;
+/*
+ * While we hold the pin_queue_mutex, all objects in pin_queue_objs will
+ * stay pinned, which means they can't move, therefore they can be scanned.
+ */
+static SgenPointerQueue pin_queue_objs;
+static mono_mutex_t pin_queue_mutex;
#define PIN_HASH_SIZE 1024
static void *pin_hash_filter [PIN_HASH_SIZE];
+void
+sgen_pinning_init (void)
+{
+ mono_os_mutex_init (&pin_queue_mutex);
+}
+
void
sgen_init_pinning (void)
{
pin_queue.mem_type = INTERNAL_MEM_PIN_QUEUE;
}
+void
+sgen_init_pinning_for_conc (void)
+{
+ mono_os_mutex_lock (&pin_queue_mutex);
+ sgen_pointer_queue_clear (&pin_queue_objs);
+}
+
void
sgen_finish_pinning (void)
{
sgen_pointer_queue_clear (&pin_queue);
}
+void
+sgen_finish_pinning_for_conc (void)
+{
+ mono_os_mutex_unlock (&pin_queue_mutex);
+}
+
+void
+sgen_pinning_register_pinned_in_nursery (GCObject *obj)
+{
+ sgen_pointer_queue_add (&pin_queue_objs, obj);
+}
+
+void
+sgen_scan_pin_queue_objects (ScanCopyContext ctx)
+{
+ int i;
+ ScanObjectFunc scan_func = ctx.ops->scan_object;
+
+ mono_os_mutex_lock (&pin_queue_mutex);
+ for (i = 0; i < pin_queue_objs.next_slot; ++i) {
+ GCObject *obj = (GCObject *)pin_queue_objs.data [i];
+ scan_func (obj, sgen_obj_get_descriptor_safe (obj), ctx.queue);
+ }
+ mono_os_mutex_unlock (&pin_queue_mutex);
+}
+
void
sgen_pin_stage_ptr (void *ptr)
{
SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Can only cement pointers to nursery objects");
if (!hash [i].obj) {
- SGEN_ASSERT (5, !hash [i].count, "Cementing hash inconsistent");
- hash [i].obj = obj;
+ GCObject *old_obj;
+ old_obj = InterlockedCompareExchangePointer ((gpointer*)&hash [i].obj, obj, NULL);
+ /* Check if the slot was occupied by some other object */
+ if (old_obj != NULL && old_obj != obj)
+ return FALSE;
} else if (hash [i].obj != obj) {
return FALSE;
}
if (hash [i].count >= SGEN_CEMENT_THRESHOLD)
return TRUE;
- ++hash [i].count;
- if (hash [i].count == SGEN_CEMENT_THRESHOLD) {
+ if (InterlockedIncrement ((gint32*)&hash [i].count) == SGEN_CEMENT_THRESHOLD) {
SGEN_ASSERT (9, sgen_get_current_collection_generation () >= 0, "We can only cement objects when we're in a collection pause.");
SGEN_ASSERT (9, SGEN_OBJECT_IS_PINNED (obj), "Can only cement pinned objects");
SGEN_CEMENT_OBJECT (obj);