aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-02 16:16:42 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-02 16:16:42 +0000
commitc8a706fe6242a553960ccc3071a4e75ceba6f3d2 (patch)
treee68691a013a24d3082b51b85a0837ccd50029e7c /exec.c
parent30813cea9b6166f2302a973d57c5818273f6c4d2 (diff)
Multithreaded locking for mmap().
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4654 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/exec.c b/exec.c
index a2e71f0b80..4480dfa177 100644
--- a/exec.c
+++ b/exec.c
@@ -234,6 +234,7 @@ static void page_init(void)
FILE *f;
int n;
+ mmap_lock();
last_brk = (unsigned long)sbrk(0);
f = fopen("/proc/self/maps", "r");
if (f) {
@@ -251,6 +252,7 @@ static void page_init(void)
} while (!feof(f));
fclose(f);
}
+ mmap_unlock();
}
#endif
}
@@ -326,6 +328,8 @@ static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
static void tlb_protect_code(ram_addr_t ram_addr);
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
target_ulong vaddr);
+#define mmap_lock() do { } while(0)
+#define mmap_unlock() do { } while(0)
#endif
#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
@@ -1049,6 +1053,9 @@ void tb_link_phys(TranslationBlock *tb,
unsigned int h;
TranslationBlock **ptb;
+ /* Grab the mmap lock to stop another thread invalidating this TB
+ before we are done. */
+ mmap_lock();
/* add in the physical hash table */
h = tb_phys_hash_func(phys_pc);
ptb = &tb_phys_hash[h];
@@ -1075,6 +1082,7 @@ void tb_link_phys(TranslationBlock *tb,
#ifdef DEBUG_TB_CHECK
tb_page_check();
#endif
+ mmap_unlock();
}
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
@@ -2002,6 +2010,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
PageDesc *p;
target_ulong addr;
+ /* mmap_lock should already be held. */
start = start & TARGET_PAGE_MASK;
end = TARGET_PAGE_ALIGN(end);
if (flags & PAGE_WRITE)
@@ -2065,11 +2074,18 @@ int page_unprotect(target_ulong address, unsigned long pc, void *puc)
PageDesc *p, *p1;
target_ulong host_start, host_end, addr;
+ /* Technically this isn't safe inside a signal handler. However we
+ know this only ever happens in a synchronous SEGV handler, so in
+ practice it seems to be ok. */
+ mmap_lock();
+
host_start = address & qemu_host_page_mask;
page_index = host_start >> TARGET_PAGE_BITS;
p1 = page_find(page_index);
- if (!p1)
+ if (!p1) {
+ mmap_unlock();
return 0;
+ }
host_end = host_start + qemu_host_page_size;
p = p1;
prot = 0;
@@ -2091,9 +2107,11 @@ int page_unprotect(target_ulong address, unsigned long pc, void *puc)
#ifdef DEBUG_TB_CHECK
tb_invalidate_check(address);
#endif
+ mmap_unlock();
return 1;
}
}
+ mmap_unlock();
return 0;
}