Пример #1
0
static void
try_free_delayed_free_items (guint32 limit)
{
	GArray *hazardous = NULL;
	DelayedFreeItem item;
	guint32 freed = 0;

	// Free all the items we can and re-add the ones we can't to the queue.
	while (mono_lock_free_array_queue_pop (&delayed_free_queue, &item)) {
		if (is_pointer_hazardous (item.p)) {
			if (!hazardous)
				hazardous = g_array_sized_new (FALSE, FALSE, sizeof (DelayedFreeItem), delayed_free_queue.num_used_entries);

			g_array_append_val (hazardous, item);
			continue;
		}

		item.free_func (item.p);
		freed++;

		if (limit && freed == limit)
			break;
	}

	if (hazardous) {
		for (gint i = 0; i < hazardous->len; i++)
			mono_lock_free_array_queue_push (&delayed_free_queue, &g_array_index (hazardous, DelayedFreeItem, i));

		g_array_free (hazardous, TRUE);
	}
}
Пример #2
0
void
mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
		gboolean free_func_might_lock, gboolean lock_free_context)
{
	int i;

	if (lock_free_context)
		g_assert (!free_func_might_lock);
	if (free_func_might_lock)
		g_assert (!lock_free_context);

	/* First try to free a few entries in the delayed free
	   table. */
	for (i = 0; i < 3; ++i)
		try_free_delayed_free_item (lock_free_context);

	/* Now see if the pointer we're freeing is hazardous.  If it
	   isn't, free it.  Otherwise put it in the delay list. */
	if (is_pointer_hazardous (p)) {
		DelayedFreeItem item = { p, free_func, free_func_might_lock };

		++hazardous_pointer_count;

		mono_lock_free_array_queue_push (&delayed_free_queue, &item);
	} else {
		free_func (p);
	}
}
Пример #3
0
/**
 * mono_thread_hazardous_queue_free:
 * \param p the pointer to free
 * \param free_func the function that can free the pointer
 * Queue \p p to be freed later. \p p will be freed once the hazard free queue is pumped.
 *
 * This function doesn't pump the free queue so try to accommodate a call at an appropriate time.
 * See \c mono_thread_hazardous_try_free_some for when it's appropriate.
 */
void
mono_thread_hazardous_queue_free (gpointer p, MonoHazardousFreeFunc free_func)
{
	DelayedFreeItem item = { p, free_func };

	mono_atomic_inc_i32 (&hazardous_pointer_count);

	mono_lock_free_array_queue_push (&delayed_free_queue, &item);

	guint32 queue_size = delayed_free_queue.num_used_entries;
	if (queue_size && queue_size_cb)
		queue_size_cb (queue_size);
}
Пример #4
0
static gboolean
try_free_delayed_free_item (gboolean lock_free_context)
{
	DelayedFreeItem item;
	gboolean popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);

	if (!popped)
		return FALSE;

	if ((lock_free_context && item.might_lock) || (is_pointer_hazardous (item.p))) {
		mono_lock_free_array_queue_push (&delayed_free_queue, &item);
		return FALSE;
	}

	item.free_func (item.p);

	return TRUE;
}
Пример #5
0
void
mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func)
{
	int i;

	/* First try to free a few entries in the delayed free
	   table. */
	for (i = 0; i < 3; ++i)
		try_free_delayed_free_item ();

	/* Now see if the pointer we're freeing is hazardous.  If it
	   isn't, free it.  Otherwise put it in the delay list. */
	if (is_pointer_hazardous (p)) {
		DelayedFreeItem item = { p, free_func };

		++mono_stats.hazardous_pointer_count;

		mono_lock_free_array_queue_push (&delayed_free_queue, &item);
	} else {
		free_func (p);
	}
}