summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-05-14 21:51:13 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-05-14 21:51:13 +0000
commiteb51d102bbd541963ac5cb98d5a8c7c2fe9453d9 (patch)
tree5d0787d2eb917d4a2107dc31e300c9b292b18b52
parent25eb44841e4125da67338320d8af0b4859c672de (diff)
downloadfocaccia-qemu-eb51d102bbd541963ac5cb98d5a8c7c2fe9453d9.tar.gz
focaccia-qemu-eb51d102bbd541963ac5cb98d5a8c7c2fe9453d9.zip
better locks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@169 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--cpu-i386.h100
-rw-r--r--exec.c4
2 files changed, 104 insertions, 0 deletions
diff --git a/cpu-i386.h b/cpu-i386.h
index 44411b0caa..008ff8cd2b 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -542,4 +542,104 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
 #define offsetof(type, field) ((size_t) &((type *)0)->field)
 #endif
 
+#ifdef __powerpc__
+static inline int testandset (int *p)
+{
+    int ret;
+    __asm__ __volatile__ (
+                          "0:    lwarx %0,0,%1 ;"
+                          "      xor. %0,%3,%0;"
+                          "      bne 1f;"
+                          "      stwcx. %2,0,%1;"
+                          "      bne- 0b;"
+                          "1:    "
+                          : "=&r" (ret)
+                          : "r" (p), "r" (1), "r" (0)
+                          : "cr0", "memory");
+    return ret;
+}
+#endif
+
+#ifdef __i386__
+static inline int testandset (int *p)
+{
+    char ret;
+    long int readval;
+    
+    __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+                          : "=q" (ret), "=m" (*p), "=a" (readval)
+                          : "r" (1), "m" (*p), "a" (0)
+                          : "memory");
+    return ret;
+}
+#endif
+
+#ifdef __s390__
+static inline int testandset (int *p)
+{
+    int ret;
+
+    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
+			  "   jl    0b"
+			  : "=&d" (ret)
+			  : "r" (1), "a" (p), "0" (*p) 
+			  : "cc", "memory" );
+    return ret;
+}
+#endif
+
+#ifdef __alpha__
+int testandset (int *p)
+{
+    int ret;
+    unsigned long one;
+
+    __asm__ __volatile__ ("0:	mov 1,%2\n"
+			  "	ldl_l %0,%1\n"
+			  "	stl_c %2,%1\n"
+			  "	beq %2,1f\n"
+			  ".subsection 2\n"
+			  "1:	br 0b\n"
+			  ".previous"
+			  : "=r" (ret), "=m" (*p), "=r" (one)
+			  : "m" (*p));
+    return ret;
+}
+#endif
+
+#ifdef __sparc__
+static inline int testandset (int *p)
+{
+	int ret;
+
+	__asm__ __volatile__("ldstub	[%1], %0"
+			     : "=r" (ret)
+			     : "r" (p)
+			     : "memory");
+
+	return (ret ? 1 : 0);
+}
+#endif
+
+typedef int spinlock_t;
+
+#define SPIN_LOCK_UNLOCKED 0
+
+static inline void spin_lock(spinlock_t *lock)
+{
+    while (testandset(lock));
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+    *lock = 0;
+}
+
+static inline int spin_trylock(spinlock_t *lock)
+{
+    return !testandset(lock);
+}
+
+extern spinlock_t tb_lock;
+
 #endif /* CPU_I386_H */
diff --git a/exec.c b/exec.c
index 0ed49c6957..8804bfab78 100644
--- a/exec.c
+++ b/exec.c
@@ -42,6 +42,8 @@
 TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
 TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
 int nb_tbs;
+/* any access to the tbs or the page table must use this lock */
+spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
 
 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
 uint8_t *code_gen_ptr;
@@ -172,6 +174,7 @@ void page_set_flags(unsigned long start, unsigned long end, int flags)
     end = TARGET_PAGE_ALIGN(end);
     if (flags & PAGE_WRITE)
         flags |= PAGE_WRITE_ORG;
+    spin_lock(&tb_lock);
     for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
         p = page_find_alloc(addr >> TARGET_PAGE_BITS);
         /* if the write protection is set, then we invalidate the code
@@ -183,6 +186,7 @@ void page_set_flags(unsigned long start, unsigned long end, int flags)
         }
         p->flags = flags;
     }
+    spin_unlock(&tb_lock);
 }
 
 void cpu_x86_tblocks_init(void)