}
static gboolean
-ptr_is_from_pinned_alloc (char *ptr)
+ptr_is_in_major_block (char *ptr, char **start, gboolean *pinned)
{
MSBlockInfo *block;
FOREACH_BLOCK_NO_LOCK (block) {
- if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE)
- return block->pinned;
+ if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) {
+ int count = MS_BLOCK_FREE / block->obj_size;
+ int i;
+
+ if (start)
+ *start = NULL;
+ for (i = 0; i <= count; ++i) {
+ if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) {
+ if (start)
+ *start = (char *)MS_BLOCK_OBJ (block, i);
+ break;
+ }
+ }
+ if (pinned)
+ *pinned = block->pinned;
+ return TRUE;
+ }
} END_FOREACH_BLOCK_NO_LOCK;
return FALSE;
}
+static gboolean
+ptr_is_from_pinned_alloc (char *ptr)
+{
+ gboolean pinned;
+ if (ptr_is_in_major_block (ptr, NULL, &pinned))
+ return pinned;
+ return FALSE;
+}
+
static void
ensure_can_access_block_free_list (MSBlockInfo *block)
{
static gboolean
major_ptr_is_in_non_pinned_space (char *ptr, char **start)
{
- MSBlockInfo *block;
-
- FOREACH_BLOCK_NO_LOCK (block) {
- if (ptr >= MS_BLOCK_FOR_BLOCK_INFO (block) && ptr <= MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE) {
- int count = MS_BLOCK_FREE / block->obj_size;
- int i;
-
- *start = NULL;
- for (i = 0; i <= count; ++i) {
- if (ptr >= (char*)MS_BLOCK_OBJ (block, i) && ptr < (char*)MS_BLOCK_OBJ (block, i + 1)) {
- *start = (char *)MS_BLOCK_OBJ (block, i);
- break;
- }
- }
- return !block->pinned;
- }
- } END_FOREACH_BLOCK_NO_LOCK;
+ gboolean pinned;
+ if (ptr_is_in_major_block (ptr, start, &pinned))
+ return !pinned;
return FALSE;
}
}
done:
+ /*
+ * Once the block is written back without the checking bit other threads are
+ * free to access it. Make sure the block state is visible before we write it
+ * back.
+ */
+ mono_memory_write_barrier ();
*block_slot = tagged_block;
return !!tagged_block;
}