* - Ludovic Henry <ludovic@xamarin.com>
*
* Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
typedef struct _MonoHandleArenaChunk MonoHandleArenaChunk;
struct _MonoHandleArenaChunk {
+ /* if next is NULL, this is the first chunk.
+ *
+ * The first chunk is special - it was allocated together with
+ * its owning arena and must not be deallocated unless the
+ * arena is being deallocated. N.B: Arenas are
+ * stack-allocated.
+ */
MonoHandleArenaChunk *next;
gsize handles_size;
MonoHandleStorage handles [HANDLES_PER_CHUNK];
struct _MonoHandleArena {
MonoHandleArenaChunk *chunk;
- MonoHandleArenaChunk *chunk_last;
MonoHandleArena *prev;
};
static inline void
chunk_free (MonoHandleArenaChunk *chunk)
{
- do {
- chunk->next = chunk_free_list;
- } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, chunk, chunk->next) != chunk->next);
+ if (chunk == NULL)
+ return;
+ while (chunk->next != NULL) {
+ MonoHandleArenaChunk *next = chunk->next;
+ chunk->next = NULL;
+ do {
+ chunk->next = chunk_free_list;
+ } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, chunk, chunk->next) != chunk->next);
+ chunk = next;
+ }
}
static MonoHandle
MonoHandleArenaChunk *chunk;
g_assert (arena->chunk);
- g_assert (arena->chunk_last);
- chunk = arena->chunk_last;
+ chunk = arena->chunk;
if (chunk->handles_size < HANDLES_PER_CHUNK) {
chunk->handles [chunk->handles_size].__private_obj = obj;
chunk->handles_size += 1;
return &chunk->handles [chunk->handles_size - 1];
- }
+ } else {
- chunk = chunk->next = chunk_alloc ();
+ MonoHandleArenaChunk *new_chunk = chunk_alloc ();
+ new_chunk->next = chunk;
+ arena->chunk = chunk = new_chunk;
- chunk->handles [0].__private_obj = obj;
- chunk->handles_size = 1;
+ chunk->handles [0].__private_obj = obj;
+ chunk->handles_size = 1;
- arena->chunk_last = chunk;
-
- return &chunk->handles [0];
+ return &chunk->handles [0];
+ }
}
MonoHandle
g_assert (arena);
arena->prev = *arena_stack;
- arena->chunk = arena->chunk_last = (MonoHandleArenaChunk*) (((char*) arena) + sizeof (MonoHandleArena));
+ arena->chunk = (MonoHandleArenaChunk*) (((char*) arena) + sizeof (MonoHandleArena));
arena->chunk->next = NULL;
arena->chunk->handles_size = 0;
g_assert (arena);
g_assert (arena->chunk);
- g_assert (arena->chunk_last);
g_assert (arena_stack);
*arena_stack = arena->prev;
for (chunk = arena->chunk; chunk; chunk = next) {
next = chunk->next;
memset (&chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK);
- if (chunk != arena->chunk)
+ if (next != NULL)
chunk_free (chunk);
}
}
}
void
-mono_handle_arena_initialize (MonoHandleArena **arena_stack)
+mono_handle_arena_init (MonoHandleArena **arena_stack)
{
mono_lazy_initialize (&arena_status, initialize);
mono_gc_register_root ((char*) arena_stack, sizeof (MonoHandleArena*), arena_desc, MONO_ROOT_SOURCE_HANDLE, "runtime threads handle arena");
}
void
-mono_handle_arena_deinitialize (MonoHandleArena **arena_stack)
+mono_handle_arena_cleanup (MonoHandleArena **arena_stack)
{
mono_gc_deregister_root ((char*) arena_stack);
}